tailwindcss 3.1.8 → 3.2.1
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 +64 -3
- package/README.md +6 -5
- package/lib/cli/build/deps.js +54 -0
- package/lib/cli/build/index.js +44 -0
- package/lib/cli/build/plugin.js +351 -0
- package/lib/cli/build/utils.js +78 -0
- package/lib/cli/build/watching.js +113 -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.js +11 -590
- package/lib/corePlugins.js +332 -108
- package/lib/css/preflight.css +5 -0
- package/lib/featureFlags.js +7 -4
- package/lib/index.js +6 -1
- package/lib/lib/content.js +167 -0
- package/lib/lib/defaultExtractor.js +15 -10
- package/lib/lib/detectNesting.js +2 -2
- package/lib/lib/evaluateTailwindFunctions.js +17 -1
- package/lib/lib/expandApplyAtRules.js +66 -37
- package/lib/lib/expandTailwindAtRules.js +10 -42
- package/lib/lib/findAtConfigPath.js +44 -0
- package/lib/lib/generateRules.js +180 -93
- package/lib/lib/normalizeTailwindDirectives.js +1 -1
- package/lib/lib/offsets.js +217 -0
- package/lib/lib/regex.js +1 -1
- package/lib/lib/setupContextUtils.js +339 -100
- package/lib/lib/setupTrackingContext.js +5 -39
- package/lib/lib/sharedState.js +2 -0
- package/lib/public/colors.js +1 -1
- package/lib/util/buildMediaQuery.js +6 -3
- package/lib/util/configurePlugins.js +1 -1
- package/lib/util/dataTypes.js +15 -19
- package/lib/util/formatVariantSelector.js +92 -8
- package/lib/util/getAllConfigs.js +14 -3
- package/lib/util/isValidArbitraryValue.js +1 -1
- package/lib/util/nameClass.js +3 -0
- package/lib/util/negateValue.js +15 -2
- package/lib/util/normalizeConfig.js +17 -3
- package/lib/util/normalizeScreens.js +100 -3
- package/lib/util/parseAnimationValue.js +1 -1
- package/lib/util/parseBoxShadowValue.js +1 -1
- package/lib/util/parseDependency.js +33 -54
- package/lib/util/parseGlob.js +34 -0
- package/lib/util/parseObjectStyles.js +1 -1
- package/lib/util/pluginUtils.js +87 -17
- package/lib/util/resolveConfig.js +2 -2
- package/lib/util/splitAtTopLevelOnly.js +31 -81
- package/lib/util/transformThemeValue.js +9 -2
- package/lib/util/validateConfig.js +1 -1
- package/lib/util/validateFormalSyntax.js +24 -0
- package/package.json +14 -13
- package/peers/index.js +3263 -1887
- package/plugin.d.ts +3 -3
- package/scripts/release-channel.js +18 -0
- package/scripts/release-notes.js +21 -0
- package/src/cli/build/deps.js +56 -0
- package/src/cli/build/index.js +45 -0
- package/src/cli/build/plugin.js +417 -0
- package/src/cli/build/utils.js +76 -0
- package/src/cli/build/watching.js +134 -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.js +4 -696
- package/src/corePlugins.js +262 -39
- package/src/css/preflight.css +5 -0
- package/src/featureFlags.js +12 -2
- package/src/index.js +5 -0
- package/src/lib/content.js +205 -0
- package/src/lib/defaultExtractor.js +3 -0
- package/src/lib/evaluateTailwindFunctions.js +22 -1
- package/src/lib/expandApplyAtRules.js +70 -29
- package/src/lib/expandTailwindAtRules.js +8 -46
- package/src/lib/findAtConfigPath.js +48 -0
- package/src/lib/generateRules.js +223 -101
- package/src/lib/offsets.js +270 -0
- package/src/lib/setupContextUtils.js +376 -89
- package/src/lib/setupTrackingContext.js +4 -45
- package/src/lib/sharedState.js +2 -0
- package/src/util/buildMediaQuery.js +5 -3
- package/src/util/dataTypes.js +15 -17
- package/src/util/formatVariantSelector.js +113 -9
- package/src/util/getAllConfigs.js +14 -2
- package/src/util/nameClass.js +4 -0
- package/src/util/negateValue.js +10 -2
- package/src/util/normalizeConfig.js +22 -2
- package/src/util/normalizeScreens.js +99 -4
- package/src/util/parseBoxShadowValue.js +1 -1
- package/src/util/parseDependency.js +37 -42
- package/src/util/parseGlob.js +24 -0
- package/src/util/pluginUtils.js +96 -14
- package/src/util/resolveConfig.js +1 -1
- package/src/util/splitAtTopLevelOnly.js +23 -49
- package/src/util/transformThemeValue.js +9 -1
- package/src/util/validateFormalSyntax.js +34 -0
- package/stubs/defaultConfig.stub.js +20 -3
- package/types/config.d.ts +48 -13
- package/types/generated/default-theme.d.ts +11 -0
|
@@ -4,7 +4,6 @@ import postcss from 'postcss'
|
|
|
4
4
|
import dlv from 'dlv'
|
|
5
5
|
import selectorParser from 'postcss-selector-parser'
|
|
6
6
|
|
|
7
|
-
import { flagEnabled } from '../featureFlags.js'
|
|
8
7
|
import transformThemeValue from '../util/transformThemeValue'
|
|
9
8
|
import parseObjectStyles from '../util/parseObjectStyles'
|
|
10
9
|
import prefixSelector from '../util/prefixSelector'
|
|
@@ -12,7 +11,6 @@ import isPlainObject from '../util/isPlainObject'
|
|
|
12
11
|
import escapeClassName from '../util/escapeClassName'
|
|
13
12
|
import nameClass, { formatClass } from '../util/nameClass'
|
|
14
13
|
import { coerceValue } from '../util/pluginUtils'
|
|
15
|
-
import bigSign from '../util/bigSign'
|
|
16
14
|
import { variantPlugins, corePlugins } from '../corePlugins'
|
|
17
15
|
import * as sharedState from './sharedState'
|
|
18
16
|
import { env } from './sharedState'
|
|
@@ -20,16 +18,41 @@ import { toPath } from '../util/toPath'
|
|
|
20
18
|
import log from '../util/log'
|
|
21
19
|
import negateValue from '../util/negateValue'
|
|
22
20
|
import isValidArbitraryValue from '../util/isValidArbitraryValue'
|
|
23
|
-
import { generateRules } from './generateRules'
|
|
21
|
+
import { generateRules, getClassNameFromSelector } from './generateRules'
|
|
24
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'
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
const VARIANT_TYPES = {
|
|
28
|
+
AddVariant: Symbol.for('ADD_VARIANT'),
|
|
29
|
+
MatchVariant: Symbol.for('MATCH_VARIANT'),
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const VARIANT_INFO = {
|
|
33
|
+
Base: 1 << 0,
|
|
34
|
+
Dynamic: 1 << 1,
|
|
35
|
+
}
|
|
27
36
|
|
|
28
37
|
function prefix(context, selector) {
|
|
29
38
|
let prefix = context.tailwindConfig.prefix
|
|
30
39
|
return typeof prefix === 'function' ? prefix(selector) : prefix + selector
|
|
31
40
|
}
|
|
32
41
|
|
|
42
|
+
function normalizeOptionTypes({ type = 'any', ...options }) {
|
|
43
|
+
let types = [].concat(type)
|
|
44
|
+
|
|
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
|
+
|
|
33
56
|
function parseVariantFormatString(input) {
|
|
34
57
|
if (input.includes('{')) {
|
|
35
58
|
if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`)
|
|
@@ -201,6 +224,13 @@ export function parseVariant(variant) {
|
|
|
201
224
|
}
|
|
202
225
|
}
|
|
203
226
|
|
|
227
|
+
/**
|
|
228
|
+
*
|
|
229
|
+
* @param {any} tailwindConfig
|
|
230
|
+
* @param {any} context
|
|
231
|
+
* @param {object} param2
|
|
232
|
+
* @param {Offsets} param2.offsets
|
|
233
|
+
*/
|
|
204
234
|
function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offsets, classList }) {
|
|
205
235
|
function getConfigValue(path, defaultValue) {
|
|
206
236
|
return path ? dlv(tailwindConfig, path, defaultValue) : tailwindConfig
|
|
@@ -235,6 +265,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
235
265
|
}
|
|
236
266
|
)
|
|
237
267
|
|
|
268
|
+
let variantIdentifier = 0
|
|
238
269
|
let api = {
|
|
239
270
|
postcss,
|
|
240
271
|
prefix: applyConfiguredPrefix,
|
|
@@ -255,7 +286,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
255
286
|
addBase(base) {
|
|
256
287
|
for (let [identifier, rule] of withIdentifiers(base)) {
|
|
257
288
|
let prefixedIdentifier = prefixIdentifier(identifier, {})
|
|
258
|
-
let offset = offsets.base
|
|
289
|
+
let offset = offsets.create('base')
|
|
259
290
|
|
|
260
291
|
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
|
|
261
292
|
context.candidateRuleMap.set(prefixedIdentifier, [])
|
|
@@ -284,7 +315,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
284
315
|
|
|
285
316
|
context.candidateRuleMap
|
|
286
317
|
.get(prefixedIdentifier)
|
|
287
|
-
.push([{ sort: offsets.
|
|
318
|
+
.push([{ sort: offsets.create('defaults'), layer: 'defaults' }, rule])
|
|
288
319
|
}
|
|
289
320
|
},
|
|
290
321
|
addComponents(components, options) {
|
|
@@ -307,7 +338,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
307
338
|
|
|
308
339
|
context.candidateRuleMap
|
|
309
340
|
.get(prefixedIdentifier)
|
|
310
|
-
.push([{ sort: offsets.components
|
|
341
|
+
.push([{ sort: offsets.create('components'), layer: 'components', options }, rule])
|
|
311
342
|
}
|
|
312
343
|
},
|
|
313
344
|
addUtilities(utilities, options) {
|
|
@@ -330,18 +361,19 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
330
361
|
|
|
331
362
|
context.candidateRuleMap
|
|
332
363
|
.get(prefixedIdentifier)
|
|
333
|
-
.push([{ sort: offsets.utilities
|
|
364
|
+
.push([{ sort: offsets.create('utilities'), layer: 'utilities', options }, rule])
|
|
334
365
|
}
|
|
335
366
|
},
|
|
336
367
|
matchUtilities: function (utilities, options) {
|
|
337
368
|
let defaultOptions = {
|
|
338
369
|
respectPrefix: true,
|
|
339
370
|
respectImportant: true,
|
|
371
|
+
modifiers: false,
|
|
340
372
|
}
|
|
341
373
|
|
|
342
|
-
options = { ...defaultOptions, ...options }
|
|
374
|
+
options = normalizeOptionTypes({ ...defaultOptions, ...options })
|
|
343
375
|
|
|
344
|
-
let offset = offsets.utilities
|
|
376
|
+
let offset = offsets.create('utilities')
|
|
345
377
|
|
|
346
378
|
for (let identifier in utilities) {
|
|
347
379
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
@@ -350,24 +382,51 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
350
382
|
classList.add([prefixedIdentifier, options])
|
|
351
383
|
|
|
352
384
|
function wrapped(modifier, { isOnlyPlugin }) {
|
|
353
|
-
let
|
|
354
|
-
|
|
355
|
-
|
|
385
|
+
let [value, coercedType, utilityModifier] = coerceValue(
|
|
386
|
+
options.types,
|
|
387
|
+
modifier,
|
|
388
|
+
options,
|
|
389
|
+
tailwindConfig
|
|
390
|
+
)
|
|
356
391
|
|
|
357
392
|
if (value === undefined) {
|
|
358
393
|
return []
|
|
359
394
|
}
|
|
360
395
|
|
|
361
|
-
if (!
|
|
362
|
-
|
|
396
|
+
if (!options.types.some(({ type }) => type === coercedType)) {
|
|
397
|
+
if (isOnlyPlugin) {
|
|
398
|
+
log.warn([
|
|
399
|
+
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
|
|
400
|
+
`You can safely update it to \`${identifier}-${modifier.replace(
|
|
401
|
+
coercedType + ':',
|
|
402
|
+
''
|
|
403
|
+
)}\`.`,
|
|
404
|
+
])
|
|
405
|
+
} else {
|
|
406
|
+
return []
|
|
407
|
+
}
|
|
363
408
|
}
|
|
364
409
|
|
|
365
410
|
if (!isValidArbitraryValue(value)) {
|
|
366
411
|
return []
|
|
367
412
|
}
|
|
368
413
|
|
|
414
|
+
let extras = {
|
|
415
|
+
get modifier() {
|
|
416
|
+
if (!options.modifiers) {
|
|
417
|
+
log.warn(`modifier-used-without-options-for-${identifier}`, [
|
|
418
|
+
'Your plugin must set `modifiers: true` in its options to support modifiers.',
|
|
419
|
+
])
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
return utilityModifier
|
|
423
|
+
},
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
|
|
427
|
+
|
|
369
428
|
let ruleSets = []
|
|
370
|
-
.concat(rule(value))
|
|
429
|
+
.concat(modifiersEnabled ? rule(value, extras) : rule(value))
|
|
371
430
|
.filter(Boolean)
|
|
372
431
|
.map((declaration) => ({
|
|
373
432
|
[nameClass(identifier, modifier)]: declaration,
|
|
@@ -389,11 +448,12 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
389
448
|
let defaultOptions = {
|
|
390
449
|
respectPrefix: true,
|
|
391
450
|
respectImportant: false,
|
|
451
|
+
modifiers: false,
|
|
392
452
|
}
|
|
393
453
|
|
|
394
|
-
options = { ...defaultOptions, ...options }
|
|
454
|
+
options = normalizeOptionTypes({ ...defaultOptions, ...options })
|
|
395
455
|
|
|
396
|
-
let offset = offsets.components
|
|
456
|
+
let offset = offsets.create('components')
|
|
397
457
|
|
|
398
458
|
for (let identifier in components) {
|
|
399
459
|
let prefixedIdentifier = prefixIdentifier(identifier, options)
|
|
@@ -402,15 +462,18 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
402
462
|
classList.add([prefixedIdentifier, options])
|
|
403
463
|
|
|
404
464
|
function wrapped(modifier, { isOnlyPlugin }) {
|
|
405
|
-
let
|
|
406
|
-
|
|
407
|
-
|
|
465
|
+
let [value, coercedType, utilityModifier] = coerceValue(
|
|
466
|
+
options.types,
|
|
467
|
+
modifier,
|
|
468
|
+
options,
|
|
469
|
+
tailwindConfig
|
|
470
|
+
)
|
|
408
471
|
|
|
409
472
|
if (value === undefined) {
|
|
410
473
|
return []
|
|
411
474
|
}
|
|
412
475
|
|
|
413
|
-
if (!
|
|
476
|
+
if (!options.types.some(({ type }) => type === coercedType)) {
|
|
414
477
|
if (isOnlyPlugin) {
|
|
415
478
|
log.warn([
|
|
416
479
|
`Unnecessary typehint \`${coercedType}\` in \`${identifier}-${modifier}\`.`,
|
|
@@ -428,8 +491,22 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
428
491
|
return []
|
|
429
492
|
}
|
|
430
493
|
|
|
494
|
+
let extras = {
|
|
495
|
+
get modifier() {
|
|
496
|
+
if (!options.modifiers) {
|
|
497
|
+
log.warn(`modifier-used-without-options-for-${identifier}`, [
|
|
498
|
+
'Your plugin must set `modifiers: true` in its options to support modifiers.',
|
|
499
|
+
])
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
return utilityModifier
|
|
503
|
+
},
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
|
|
507
|
+
|
|
431
508
|
let ruleSets = []
|
|
432
|
-
.concat(rule(value))
|
|
509
|
+
.concat(modifiersEnabled ? rule(value, extras) : rule(value))
|
|
433
510
|
.filter(Boolean)
|
|
434
511
|
.map((declaration) => ({
|
|
435
512
|
[nameClass(identifier, modifier)]: declaration,
|
|
@@ -456,7 +533,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
456
533
|
let result = variantFunction(
|
|
457
534
|
Object.assign(
|
|
458
535
|
{ modifySelectors, container, separator },
|
|
459
|
-
|
|
536
|
+
options.type === VARIANT_TYPES.MatchVariant && { args, wrap, format }
|
|
460
537
|
)
|
|
461
538
|
)
|
|
462
539
|
|
|
@@ -489,23 +566,58 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
|
|
|
489
566
|
|
|
490
567
|
insertInto(variantList, variantName, options)
|
|
491
568
|
variantMap.set(variantName, variantFunctions)
|
|
569
|
+
context.variantOptions.set(variantName, options)
|
|
492
570
|
},
|
|
493
|
-
|
|
571
|
+
matchVariant(variant, variantFn, options) {
|
|
572
|
+
// A unique identifier that "groups" these variants together.
|
|
573
|
+
// This is for internal use only which is why it is not present in the types
|
|
574
|
+
let id = options?.id ?? ++variantIdentifier
|
|
575
|
+
let isSpecial = variant === '@'
|
|
494
576
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
for (let
|
|
498
|
-
|
|
499
|
-
api.addVariant(`${variant}-${k}`, variants[variant](v))
|
|
500
|
-
}
|
|
577
|
+
let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
|
|
578
|
+
|
|
579
|
+
for (let [key, value] of Object.entries(options?.values ?? {})) {
|
|
580
|
+
if (key === 'DEFAULT') continue
|
|
501
581
|
|
|
502
582
|
api.addVariant(
|
|
503
|
-
variant
|
|
504
|
-
|
|
505
|
-
|
|
583
|
+
isSpecial ? `${variant}${key}` : `${variant}-${key}`,
|
|
584
|
+
({ args, container }) =>
|
|
585
|
+
variantFn(
|
|
586
|
+
value,
|
|
587
|
+
modifiersEnabled ? { modifier: args.modifier, container } : { container }
|
|
588
|
+
),
|
|
589
|
+
{
|
|
590
|
+
...options,
|
|
591
|
+
value,
|
|
592
|
+
id,
|
|
593
|
+
type: VARIANT_TYPES.MatchVariant,
|
|
594
|
+
variantInfo: VARIANT_INFO.Base,
|
|
595
|
+
}
|
|
506
596
|
)
|
|
507
597
|
}
|
|
508
|
-
|
|
598
|
+
|
|
599
|
+
let hasDefault = 'DEFAULT' in (options?.values ?? {})
|
|
600
|
+
|
|
601
|
+
api.addVariant(
|
|
602
|
+
variant,
|
|
603
|
+
({ args, container }) => {
|
|
604
|
+
if (args.value === sharedState.NONE && !hasDefault) {
|
|
605
|
+
return null
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
return variantFn(
|
|
609
|
+
args.value === sharedState.NONE ? options.values.DEFAULT : args.value,
|
|
610
|
+
modifiersEnabled ? { modifier: args.modifier, container } : { container }
|
|
611
|
+
)
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
...options,
|
|
615
|
+
id,
|
|
616
|
+
type: VARIANT_TYPES.MatchVariant,
|
|
617
|
+
variantInfo: VARIANT_INFO.Dynamic,
|
|
618
|
+
}
|
|
619
|
+
)
|
|
620
|
+
},
|
|
509
621
|
}
|
|
510
622
|
|
|
511
623
|
return api
|
|
@@ -624,8 +736,11 @@ function resolvePlugins(context, root) {
|
|
|
624
736
|
let beforeVariants = [
|
|
625
737
|
variantPlugins['pseudoElementVariants'],
|
|
626
738
|
variantPlugins['pseudoClassVariants'],
|
|
739
|
+
variantPlugins['ariaVariants'],
|
|
740
|
+
variantPlugins['dataVariants'],
|
|
627
741
|
]
|
|
628
742
|
let afterVariants = [
|
|
743
|
+
variantPlugins['supportsVariants'],
|
|
629
744
|
variantPlugins['directionVariants'],
|
|
630
745
|
variantPlugins['reducedMotionVariants'],
|
|
631
746
|
variantPlugins['prefersContrastVariants'],
|
|
@@ -641,13 +756,10 @@ function resolvePlugins(context, root) {
|
|
|
641
756
|
function registerPlugins(plugins, context) {
|
|
642
757
|
let variantList = []
|
|
643
758
|
let variantMap = new Map()
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
utilities: 0n,
|
|
649
|
-
user: 0n,
|
|
650
|
-
}
|
|
759
|
+
context.variantMap = variantMap
|
|
760
|
+
|
|
761
|
+
let offsets = new Offsets()
|
|
762
|
+
context.offsets = offsets
|
|
651
763
|
|
|
652
764
|
let classList = new Set()
|
|
653
765
|
|
|
@@ -668,49 +780,17 @@ function registerPlugins(plugins, context) {
|
|
|
668
780
|
}
|
|
669
781
|
}
|
|
670
782
|
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
offsets.defaults,
|
|
674
|
-
offsets.components,
|
|
675
|
-
offsets.utilities,
|
|
676
|
-
offsets.user,
|
|
677
|
-
])
|
|
678
|
-
let reservedBits = BigInt(highestOffset.toString(2).length)
|
|
679
|
-
|
|
680
|
-
// A number one less than the top range of the highest offset area
|
|
681
|
-
// so arbitrary properties are always sorted at the end.
|
|
682
|
-
context.arbitraryPropertiesSort = ((1n << reservedBits) << 0n) - 1n
|
|
683
|
-
|
|
684
|
-
context.layerOrder = {
|
|
685
|
-
defaults: (1n << reservedBits) << 0n,
|
|
686
|
-
base: (1n << reservedBits) << 1n,
|
|
687
|
-
components: (1n << reservedBits) << 2n,
|
|
688
|
-
utilities: (1n << reservedBits) << 3n,
|
|
689
|
-
user: (1n << reservedBits) << 4n,
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
reservedBits += 5n
|
|
693
|
-
|
|
694
|
-
let offset = 0
|
|
695
|
-
context.variantOrder = new Map(
|
|
696
|
-
variantList
|
|
697
|
-
.map((variant, i) => {
|
|
698
|
-
let variantFunctions = variantMap.get(variant).length
|
|
699
|
-
let bits = (1n << BigInt(i + offset)) << reservedBits
|
|
700
|
-
offset += variantFunctions - 1
|
|
701
|
-
return [variant, bits]
|
|
702
|
-
})
|
|
703
|
-
.sort(([, a], [, z]) => bigSign(a - z))
|
|
704
|
-
)
|
|
705
|
-
|
|
706
|
-
context.minimumScreen = [...context.variantOrder.values()].shift()
|
|
783
|
+
// Make sure to record bit masks for every variant
|
|
784
|
+
offsets.recordVariants(variantList, (variant) => variantMap.get(variant).length)
|
|
707
785
|
|
|
708
786
|
// Build variantMap
|
|
709
787
|
for (let [variantName, variantFunctions] of variantMap.entries()) {
|
|
710
|
-
let sort = context.variantOrder.get(variantName)
|
|
711
788
|
context.variantMap.set(
|
|
712
789
|
variantName,
|
|
713
|
-
variantFunctions.map((variantFunction, idx) => [
|
|
790
|
+
variantFunctions.map((variantFunction, idx) => [
|
|
791
|
+
offsets.forVariant(variantName, idx),
|
|
792
|
+
variantFunction,
|
|
793
|
+
])
|
|
714
794
|
)
|
|
715
795
|
}
|
|
716
796
|
|
|
@@ -764,7 +844,7 @@ function registerPlugins(plugins, context) {
|
|
|
764
844
|
]
|
|
765
845
|
}
|
|
766
846
|
|
|
767
|
-
if (
|
|
847
|
+
if (options.types.some(({ type }) => type === 'color')) {
|
|
768
848
|
classes = [
|
|
769
849
|
...classes,
|
|
770
850
|
...classes.flatMap((cls) =>
|
|
@@ -816,26 +896,41 @@ function registerPlugins(plugins, context) {
|
|
|
816
896
|
}
|
|
817
897
|
}
|
|
818
898
|
|
|
899
|
+
let darkClassName = [].concat(context.tailwindConfig.darkMode ?? 'media')[1] ?? 'dark'
|
|
900
|
+
|
|
819
901
|
// A list of utilities that are used by certain Tailwind CSS utilities but
|
|
820
902
|
// that don't exist on their own. This will result in them "not existing" and
|
|
821
903
|
// sorting could be weird since you still require them in order to make the
|
|
822
|
-
// host
|
|
823
|
-
let parasiteUtilities =
|
|
904
|
+
// host utilities work properly. (Thanks Biology)
|
|
905
|
+
let parasiteUtilities = [
|
|
906
|
+
prefix(context, darkClassName),
|
|
907
|
+
prefix(context, 'group'),
|
|
908
|
+
prefix(context, 'peer'),
|
|
909
|
+
]
|
|
824
910
|
context.getClassOrder = function getClassOrder(classes) {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
911
|
+
// Non-util classes won't be generated, so we default them to null
|
|
912
|
+
let sortedClassNames = new Map(classes.map((className) => [className, null]))
|
|
913
|
+
|
|
914
|
+
// Sort all classes in order
|
|
915
|
+
// Non-tailwind classes won't be generated and will be left as `null`
|
|
916
|
+
let rules = generateRules(new Set(classes), context)
|
|
917
|
+
rules = context.offsets.sort(rules)
|
|
918
|
+
|
|
919
|
+
let idx = BigInt(parasiteUtilities.length)
|
|
920
|
+
|
|
921
|
+
for (const [, rule] of rules) {
|
|
922
|
+
sortedClassNames.set(rule.raws.tailwind.candidate, idx++)
|
|
829
923
|
}
|
|
830
924
|
|
|
831
925
|
return classes.map((className) => {
|
|
832
926
|
let order = sortedClassNames.get(className) ?? null
|
|
927
|
+
let parasiteIndex = parasiteUtilities.indexOf(className)
|
|
833
928
|
|
|
834
|
-
if (order === null &&
|
|
929
|
+
if (order === null && parasiteIndex !== -1) {
|
|
835
930
|
// This will make sure that it is at the very beginning of the
|
|
836
931
|
// `components` layer which technically means 'before any
|
|
837
932
|
// components'.
|
|
838
|
-
order =
|
|
933
|
+
order = BigInt(parasiteIndex)
|
|
839
934
|
}
|
|
840
935
|
|
|
841
936
|
return [className, order]
|
|
@@ -853,6 +948,11 @@ function registerPlugins(plugins, context) {
|
|
|
853
948
|
let negativeClasses = []
|
|
854
949
|
|
|
855
950
|
for (let [key, value] of Object.entries(options?.values ?? {})) {
|
|
951
|
+
// Ignore undefined and null values
|
|
952
|
+
if (value == null) {
|
|
953
|
+
continue
|
|
954
|
+
}
|
|
955
|
+
|
|
856
956
|
output.push(formatClass(utilName, key))
|
|
857
957
|
if (options?.supportsNegativeValues && negateValue(value)) {
|
|
858
958
|
negativeClasses.push(formatClass(utilName, `-${key}`))
|
|
@@ -867,12 +967,191 @@ function registerPlugins(plugins, context) {
|
|
|
867
967
|
|
|
868
968
|
return output
|
|
869
969
|
}
|
|
970
|
+
|
|
971
|
+
// Generate a list of available variants with meta information of the type of variant.
|
|
972
|
+
context.getVariants = function getVariants() {
|
|
973
|
+
let result = []
|
|
974
|
+
for (let [name, options] of context.variantOptions.entries()) {
|
|
975
|
+
if (options.variantInfo === VARIANT_INFO.Base) continue
|
|
976
|
+
|
|
977
|
+
result.push({
|
|
978
|
+
name,
|
|
979
|
+
isArbitrary: options.type === Symbol.for('MATCH_VARIANT'),
|
|
980
|
+
values: Object.keys(options.values ?? {}),
|
|
981
|
+
hasDash: name !== '@',
|
|
982
|
+
selectors({ modifier, value } = {}) {
|
|
983
|
+
let candidate = '__TAILWIND_PLACEHOLDER__'
|
|
984
|
+
|
|
985
|
+
let rule = postcss.rule({ selector: `.${candidate}` })
|
|
986
|
+
let container = postcss.root({ nodes: [rule.clone()] })
|
|
987
|
+
|
|
988
|
+
let before = container.toString()
|
|
989
|
+
|
|
990
|
+
let fns = (context.variantMap.get(name) ?? []).flatMap(([_, fn]) => fn)
|
|
991
|
+
let formatStrings = []
|
|
992
|
+
for (let fn of fns) {
|
|
993
|
+
let localFormatStrings = []
|
|
994
|
+
|
|
995
|
+
let api = {
|
|
996
|
+
args: { modifier, value: options.values?.[value] ?? value },
|
|
997
|
+
separator: context.tailwindConfig.separator,
|
|
998
|
+
modifySelectors(modifierFunction) {
|
|
999
|
+
// Run the modifierFunction over each rule
|
|
1000
|
+
container.each((rule) => {
|
|
1001
|
+
if (rule.type !== 'rule') {
|
|
1002
|
+
return
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
rule.selectors = rule.selectors.map((selector) => {
|
|
1006
|
+
return modifierFunction({
|
|
1007
|
+
get className() {
|
|
1008
|
+
return getClassNameFromSelector(selector)
|
|
1009
|
+
},
|
|
1010
|
+
selector,
|
|
1011
|
+
})
|
|
1012
|
+
})
|
|
1013
|
+
})
|
|
1014
|
+
|
|
1015
|
+
return container
|
|
1016
|
+
},
|
|
1017
|
+
format(str) {
|
|
1018
|
+
localFormatStrings.push(str)
|
|
1019
|
+
},
|
|
1020
|
+
wrap(wrapper) {
|
|
1021
|
+
localFormatStrings.push(`@${wrapper.name} ${wrapper.params} { & }`)
|
|
1022
|
+
},
|
|
1023
|
+
container,
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
let ruleWithVariant = fn(api)
|
|
1027
|
+
if (localFormatStrings.length > 0) {
|
|
1028
|
+
formatStrings.push(localFormatStrings)
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
if (Array.isArray(ruleWithVariant)) {
|
|
1032
|
+
for (let variantFunction of ruleWithVariant) {
|
|
1033
|
+
localFormatStrings = []
|
|
1034
|
+
variantFunction(api)
|
|
1035
|
+
formatStrings.push(localFormatStrings)
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
// Reverse engineer the result of the `container`
|
|
1041
|
+
let manualFormatStrings = []
|
|
1042
|
+
let after = container.toString()
|
|
1043
|
+
|
|
1044
|
+
if (before !== after) {
|
|
1045
|
+
// Figure out all selectors
|
|
1046
|
+
container.walkRules((rule) => {
|
|
1047
|
+
let modified = rule.selector
|
|
1048
|
+
|
|
1049
|
+
// Rebuild the base selector, this is what plugin authors would do
|
|
1050
|
+
// as well. E.g.: `${variant}${separator}${className}`.
|
|
1051
|
+
// However, plugin authors probably also prepend or append certain
|
|
1052
|
+
// classes, pseudos, ids, ...
|
|
1053
|
+
let rebuiltBase = selectorParser((selectors) => {
|
|
1054
|
+
selectors.walkClasses((classNode) => {
|
|
1055
|
+
classNode.value = `${name}${context.tailwindConfig.separator}${classNode.value}`
|
|
1056
|
+
})
|
|
1057
|
+
}).processSync(modified)
|
|
1058
|
+
|
|
1059
|
+
// Now that we know the original selector, the new selector, and
|
|
1060
|
+
// the rebuild part in between, we can replace the part that plugin
|
|
1061
|
+
// authors need to rebuild with `&`, and eventually store it in the
|
|
1062
|
+
// collectedFormats. Similar to what `format('...')` would do.
|
|
1063
|
+
//
|
|
1064
|
+
// E.g.:
|
|
1065
|
+
// variant: foo
|
|
1066
|
+
// selector: .markdown > p
|
|
1067
|
+
// modified (by plugin): .foo .foo\\:markdown > p
|
|
1068
|
+
// rebuiltBase (internal): .foo\\:markdown > p
|
|
1069
|
+
// format: .foo &
|
|
1070
|
+
manualFormatStrings.push(modified.replace(rebuiltBase, '&').replace(candidate, '&'))
|
|
1071
|
+
})
|
|
1072
|
+
|
|
1073
|
+
// Figure out all atrules
|
|
1074
|
+
container.walkAtRules((atrule) => {
|
|
1075
|
+
manualFormatStrings.push(`@${atrule.name} (${atrule.params}) { & }`)
|
|
1076
|
+
})
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
let result = formatStrings.map((formatString) =>
|
|
1080
|
+
finalizeSelector(formatVariantSelector('&', ...formatString), {
|
|
1081
|
+
selector: `.${candidate}`,
|
|
1082
|
+
candidate,
|
|
1083
|
+
context,
|
|
1084
|
+
isArbitraryVariant: !(value in (options.values ?? {})),
|
|
1085
|
+
})
|
|
1086
|
+
.replace(`.${candidate}`, '&')
|
|
1087
|
+
.replace('{ & }', '')
|
|
1088
|
+
.trim()
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
if (manualFormatStrings.length > 0) {
|
|
1092
|
+
result.push(formatVariantSelector('&', ...manualFormatStrings))
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
return result
|
|
1096
|
+
},
|
|
1097
|
+
})
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
return result
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Mark as class as retroactively invalid
|
|
1106
|
+
*
|
|
1107
|
+
*
|
|
1108
|
+
* @param {string} candidate
|
|
1109
|
+
*/
|
|
1110
|
+
function markInvalidUtilityCandidate(context, candidate) {
|
|
1111
|
+
if (!context.classCache.has(candidate)) {
|
|
1112
|
+
return
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// Mark this as not being a real utility
|
|
1116
|
+
context.notClassCache.add(candidate)
|
|
1117
|
+
|
|
1118
|
+
// Remove it from any candidate-specific caches
|
|
1119
|
+
context.classCache.delete(candidate)
|
|
1120
|
+
context.applyClassCache.delete(candidate)
|
|
1121
|
+
context.candidateRuleMap.delete(candidate)
|
|
1122
|
+
context.candidateRuleCache.delete(candidate)
|
|
1123
|
+
|
|
1124
|
+
// Ensure the stylesheet gets rebuilt
|
|
1125
|
+
context.stylesheetCache = null
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* Mark as class as retroactively invalid
|
|
1130
|
+
*
|
|
1131
|
+
* @param {import('postcss').Node} node
|
|
1132
|
+
*/
|
|
1133
|
+
function markInvalidUtilityNode(context, node) {
|
|
1134
|
+
let candidate = node.raws.tailwind.candidate
|
|
1135
|
+
|
|
1136
|
+
if (!candidate) {
|
|
1137
|
+
return
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
for (const entry of context.ruleCache) {
|
|
1141
|
+
if (entry[1].raws.tailwind.candidate === candidate) {
|
|
1142
|
+
context.ruleCache.delete(entry)
|
|
1143
|
+
// context.postCssNodeCache.delete(node)
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
markInvalidUtilityCandidate(context, candidate)
|
|
870
1148
|
}
|
|
871
1149
|
|
|
872
1150
|
export function createContext(tailwindConfig, changedContent = [], root = postcss.root()) {
|
|
873
1151
|
let context = {
|
|
874
1152
|
disposables: [],
|
|
875
1153
|
ruleCache: new Set(),
|
|
1154
|
+
candidateRuleCache: new Map(),
|
|
876
1155
|
classCache: new Map(),
|
|
877
1156
|
applyClassCache: new Map(),
|
|
878
1157
|
notClassCache: new Set(),
|
|
@@ -882,6 +1161,10 @@ export function createContext(tailwindConfig, changedContent = [], root = postcs
|
|
|
882
1161
|
changedContent: changedContent,
|
|
883
1162
|
variantMap: new Map(),
|
|
884
1163
|
stylesheetCache: null,
|
|
1164
|
+
variantOptions: new Map(),
|
|
1165
|
+
|
|
1166
|
+
markInvalidUtilityCandidate: (candidate) => markInvalidUtilityCandidate(context, candidate),
|
|
1167
|
+
markInvalidUtilityNode: (node) => markInvalidUtilityNode(context, node),
|
|
885
1168
|
}
|
|
886
1169
|
|
|
887
1170
|
let resolvedPlugins = resolvePlugins(context, root)
|
|
@@ -960,6 +1243,10 @@ export function getContext(
|
|
|
960
1243
|
|
|
961
1244
|
let context = createContext(tailwindConfig, [], root)
|
|
962
1245
|
|
|
1246
|
+
Object.assign(context, {
|
|
1247
|
+
userConfigPath,
|
|
1248
|
+
})
|
|
1249
|
+
|
|
963
1250
|
trackModified([...contextDependencies], getFileModifiedMap(context))
|
|
964
1251
|
|
|
965
1252
|
// ---
|