tailwindcss 3.0.18 → 3.0.19
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 +14 -2
- package/LICENSE +1 -2
- package/lib/css/preflight.css +1 -1
- package/lib/lib/generateRules.js +67 -29
- package/lib/lib/setupContextUtils.js +14 -1
- package/lib/util/parseBoxShadowValue.js +1 -1
- package/lib/util/prefixSelector.js +4 -5
- package/package.json +5 -10
- package/peers/index.js +173 -409
- package/src/css/preflight.css +1 -1
- package/src/lib/generateRules.js +74 -24
- package/src/lib/setupContextUtils.js +16 -3
- package/src/util/parseBoxShadowValue.js +1 -1
- package/src/util/prefixSelector.js +7 -5
package/src/css/preflight.css
CHANGED
package/src/lib/generateRules.js
CHANGED
|
@@ -25,33 +25,33 @@ function getClassNameFromSelector(selector) {
|
|
|
25
25
|
// Example with dynamic classes:
|
|
26
26
|
// ['grid-cols', '[[linename],1fr,auto]']
|
|
27
27
|
// ['grid', 'cols-[[linename],1fr,auto]']
|
|
28
|
-
function* candidatePermutations(candidate
|
|
29
|
-
|
|
30
|
-
return
|
|
31
|
-
}
|
|
28
|
+
function* candidatePermutations(candidate) {
|
|
29
|
+
let lastIndex = Infinity
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
while (lastIndex >= 0) {
|
|
32
|
+
let dashIdx
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
if (lastIndex === Infinity && candidate.endsWith(']')) {
|
|
35
|
+
let bracketIdx = candidate.indexOf('[')
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
// If character before `[` isn't a dash or a slash, this isn't a dynamic class
|
|
38
|
+
// eg. string[]
|
|
39
|
+
dashIdx = ['-', '/'].includes(candidate[bracketIdx - 1]) ? bracketIdx - 1 : -1
|
|
40
|
+
} else {
|
|
41
|
+
dashIdx = candidate.lastIndexOf('-', lastIndex)
|
|
42
|
+
}
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
if (dashIdx < 0) {
|
|
45
|
+
break
|
|
46
|
+
}
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
let prefix = candidate.slice(0, dashIdx)
|
|
49
|
+
let modifier = candidate.slice(dashIdx + 1)
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
yield [prefix, modifier]
|
|
53
52
|
|
|
54
|
-
|
|
53
|
+
lastIndex = dashIdx - 1
|
|
54
|
+
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
function applyPrefix(matches, context) {
|
|
@@ -63,9 +63,23 @@ function applyPrefix(matches, context) {
|
|
|
63
63
|
let [meta] = match
|
|
64
64
|
if (meta.options.respectPrefix) {
|
|
65
65
|
let container = postcss.root({ nodes: [match[1].clone()] })
|
|
66
|
+
let classCandidate = match[1].raws.tailwind.classCandidate
|
|
67
|
+
|
|
66
68
|
container.walkRules((r) => {
|
|
67
|
-
|
|
69
|
+
// If this is a negative utility with a dash *before* the prefix we
|
|
70
|
+
// have to ensure that the generated selector matches the candidate
|
|
71
|
+
|
|
72
|
+
// Not doing this will cause `-tw-top-1` to generate the class `.tw--top-1`
|
|
73
|
+
// The disconnect between candidate <-> class can cause @apply to hard crash.
|
|
74
|
+
let shouldPrependNegative = classCandidate.startsWith('-')
|
|
75
|
+
|
|
76
|
+
r.selector = prefixSelector(
|
|
77
|
+
context.tailwindConfig.prefix,
|
|
78
|
+
r.selector,
|
|
79
|
+
shouldPrependNegative
|
|
80
|
+
)
|
|
68
81
|
})
|
|
82
|
+
|
|
69
83
|
match[1] = container.nodes[0]
|
|
70
84
|
}
|
|
71
85
|
}
|
|
@@ -262,11 +276,37 @@ function parseRules(rule, cache, options = {}) {
|
|
|
262
276
|
const IS_VALID_PROPERTY_NAME = /^[a-z_-]/
|
|
263
277
|
|
|
264
278
|
function isValidPropName(name) {
|
|
265
|
-
|
|
266
|
-
|
|
279
|
+
return IS_VALID_PROPERTY_NAME.test(name)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* @param {string} declaration
|
|
284
|
+
* @returns {boolean}
|
|
285
|
+
*/
|
|
286
|
+
function looksLikeUri(declaration) {
|
|
287
|
+
// Quick bailout for obvious non-urls
|
|
288
|
+
// This doesn't support schemes that don't use a leading // but that's unlikely to be a problem
|
|
289
|
+
if (!declaration.includes('://')) {
|
|
290
|
+
return false
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
const url = new URL(declaration)
|
|
295
|
+
return url.scheme !== '' && url.host !== ''
|
|
296
|
+
} catch (err) {
|
|
297
|
+
// Definitely not a valid url
|
|
298
|
+
return false
|
|
299
|
+
}
|
|
267
300
|
}
|
|
268
301
|
|
|
269
302
|
function isParsableCssValue(property, value) {
|
|
303
|
+
// We don't want to to treat [https://example.com] as a custom property
|
|
304
|
+
// Even though, according to the CSS grammar, it's a totally valid CSS declaration
|
|
305
|
+
// So we short-circuit here by checking if the custom property looks like a url
|
|
306
|
+
if (looksLikeUri(`${property}:${value}`)) {
|
|
307
|
+
return false
|
|
308
|
+
}
|
|
309
|
+
|
|
270
310
|
try {
|
|
271
311
|
postcss.parse(`a{${property}:${value}}`).toResult()
|
|
272
312
|
return true
|
|
@@ -345,6 +385,14 @@ function splitWithSeparator(input, separator) {
|
|
|
345
385
|
return input.split(new RegExp(`\\${separator}(?![^[]*\\])`, 'g'))
|
|
346
386
|
}
|
|
347
387
|
|
|
388
|
+
function* recordCandidates(matches, classCandidate) {
|
|
389
|
+
for (const match of matches) {
|
|
390
|
+
match[1].raws.tailwind = { classCandidate }
|
|
391
|
+
|
|
392
|
+
yield match
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
348
396
|
function* resolveMatches(candidate, context) {
|
|
349
397
|
let separator = context.tailwindConfig.separator
|
|
350
398
|
let [classCandidate, ...variants] = splitWithSeparator(candidate, separator).reverse()
|
|
@@ -456,7 +504,9 @@ function* resolveMatches(candidate, context) {
|
|
|
456
504
|
continue
|
|
457
505
|
}
|
|
458
506
|
|
|
459
|
-
matches =
|
|
507
|
+
matches = matches.flat()
|
|
508
|
+
matches = Array.from(recordCandidates(matches, classCandidate))
|
|
509
|
+
matches = applyPrefix(matches, context)
|
|
460
510
|
|
|
461
511
|
if (important) {
|
|
462
512
|
matches = applyImportant(matches, context)
|
|
@@ -666,17 +666,30 @@ function registerPlugins(plugins, context) {
|
|
|
666
666
|
|
|
667
667
|
if (checks.length > 0) {
|
|
668
668
|
let patternMatchingCount = new Map()
|
|
669
|
+
let prefixLength = context.tailwindConfig.prefix.length
|
|
669
670
|
|
|
670
671
|
for (let util of classList) {
|
|
671
672
|
let utils = Array.isArray(util)
|
|
672
673
|
? (() => {
|
|
673
674
|
let [utilName, options] = util
|
|
674
|
-
let
|
|
675
|
-
|
|
676
|
-
)
|
|
675
|
+
let values = Object.keys(options?.values ?? {})
|
|
676
|
+
let classes = values.map((value) => formatClass(utilName, value))
|
|
677
677
|
|
|
678
678
|
if (options?.supportsNegativeValues) {
|
|
679
|
+
// This is the normal negated version
|
|
680
|
+
// e.g. `-inset-1` or `-tw-inset-1`
|
|
679
681
|
classes = [...classes, ...classes.map((cls) => '-' + cls)]
|
|
682
|
+
|
|
683
|
+
// This is the negated version *after* the prefix
|
|
684
|
+
// e.g. `tw--inset-1`
|
|
685
|
+
// The prefix is already attached to util name
|
|
686
|
+
// So we add the negative after the prefix
|
|
687
|
+
classes = [
|
|
688
|
+
...classes,
|
|
689
|
+
...classes.map(
|
|
690
|
+
(cls) => cls.slice(0, prefixLength) + '-' + cls.slice(prefixLength)
|
|
691
|
+
),
|
|
692
|
+
]
|
|
680
693
|
}
|
|
681
694
|
|
|
682
695
|
return classes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
let KEYWORDS = new Set(['inset', 'inherit', 'initial', 'revert', 'unset'])
|
|
2
2
|
let COMMA = /\,(?![^(]*\))/g // Comma separator that is not located between brackets. E.g.: `cubiz-bezier(a, b, c)` these don't count.
|
|
3
3
|
let SPACE = /\ +(?![^(]*\))/g // Similar to the one above, but with spaces instead.
|
|
4
|
-
let LENGTH = /^-?(\d+)(.*?)$/g
|
|
4
|
+
let LENGTH = /^-?(\d+|\.\d+)(.*?)$/g
|
|
5
5
|
|
|
6
6
|
export function parseBoxShadowValue(input) {
|
|
7
7
|
let shadows = input.split(COMMA)
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import parser from 'postcss-selector-parser'
|
|
2
|
-
import { tap } from './tap'
|
|
3
2
|
|
|
4
|
-
export default function (prefix, selector) {
|
|
3
|
+
export default function (prefix, selector, prependNegative = false) {
|
|
5
4
|
return parser((selectors) => {
|
|
6
5
|
selectors.walkClasses((classSelector) => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
let baseClass = classSelector.value
|
|
7
|
+
let shouldPlaceNegativeBeforePrefix = prependNegative && baseClass.startsWith('-')
|
|
8
|
+
|
|
9
|
+
classSelector.value = shouldPlaceNegativeBeforePrefix
|
|
10
|
+
? `-${prefix}${baseClass.slice(1)}`
|
|
11
|
+
: `${prefix}${baseClass}`
|
|
10
12
|
})
|
|
11
13
|
}).processSync(selector)
|
|
12
14
|
}
|