tailwindcss 3.1.1 → 3.1.4

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.
@@ -12,7 +12,7 @@ export function defaultExtractor(context) {
12
12
  let results = []
13
13
 
14
14
  for (let pattern of patterns) {
15
- results.push(...(content.match(pattern) ?? []))
15
+ results = [...results, ...(content.match(pattern) ?? [])]
16
16
  }
17
17
 
18
18
  return results.filter((v) => v !== undefined).map(clipAtBalancedParens)
@@ -37,7 +37,7 @@ function* buildRegExps(context) {
37
37
  regex.any([
38
38
  regex.pattern([
39
39
  // Arbitrary values
40
- /-\[[^\s:]+\]/,
40
+ /-(?:\w+-)*\[[^\s:]+\]/,
41
41
 
42
42
  // Not immediately followed by an `{[(`
43
43
  /(?![{([]])/,
@@ -48,7 +48,7 @@ function* buildRegExps(context) {
48
48
 
49
49
  regex.pattern([
50
50
  // Arbitrary values
51
- /-\[[^\s]+\]/,
51
+ /-(?:\w+-)*\[[^\s]+\]/,
52
52
 
53
53
  // Not immediately followed by an `{[(`
54
54
  /(?![{([]])/,
@@ -64,31 +64,41 @@ function* buildRegExps(context) {
64
64
  ]),
65
65
  ])
66
66
 
67
- yield regex.pattern([
68
- // Variants
69
- '((?=((',
70
- regex.any(
71
- [
72
- regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`\\]+\]/, separator]),
73
- regex.pattern([/[^\s"'`\[\\]+/, separator]),
74
- ],
75
- true
76
- ),
77
- ')+))\\2)?',
78
-
79
- // Important (optional)
80
- /!?/,
81
-
82
- variantGroupingEnabled
83
- ? regex.any([
84
- // Or any of those things but grouped separated by commas
85
- regex.pattern([/\(/, utility, regex.zeroOrMore([/,/, utility]), /\)/]),
86
-
87
- // Arbitrary properties, constrained utilities, arbitrary values, etc…
88
- utility,
89
- ])
90
- : utility,
91
- ])
67
+ let variantPatterns = [
68
+ // Without quotes
69
+ regex.any([
70
+ regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
71
+ regex.pattern([/[^\s"'`\[\\]+/, separator]),
72
+ ]),
73
+
74
+ // With quotes allowed
75
+ regex.any([
76
+ regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
77
+ regex.pattern([/[^\s`\[\\]+/, separator]),
78
+ ]),
79
+ ]
80
+
81
+ for (const variantPattern of variantPatterns) {
82
+ yield regex.pattern([
83
+ // Variants
84
+ '((?=((',
85
+ variantPattern,
86
+ ')+))\\2)?',
87
+
88
+ // Important (optional)
89
+ /!?/,
90
+
91
+ variantGroupingEnabled
92
+ ? regex.any([
93
+ // Or any of those things but grouped separated by commas
94
+ regex.pattern([/\(/, utility, regex.zeroOrMore([/,/, utility]), /\)/]),
95
+
96
+ // Arbitrary properties, constrained utilities, arbitrary values, etc…
97
+ utility,
98
+ ])
99
+ : utility,
100
+ ])
101
+ }
92
102
 
93
103
  // 5. Inner matches
94
104
  yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
@@ -40,9 +40,7 @@ function listKeys(obj) {
40
40
  }
41
41
 
42
42
  function validatePath(config, path, defaultValue, themeOpts = {}) {
43
- const pathString = Array.isArray(path)
44
- ? pathToString(path)
45
- : path.replace(/^['"]+/g, '').replace(/['"]+$/g, '')
43
+ const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, '')
46
44
  const pathSegments = Array.isArray(path) ? path : toPath(pathString)
47
45
  const value = dlv(config.theme, pathSegments, defaultValue)
48
46
 
@@ -162,6 +160,10 @@ let nodeTypePropertyMap = {
162
160
  export default function ({ tailwindConfig: config }) {
163
161
  let functions = {
164
162
  theme: (node, path, ...defaultValue) => {
163
+ // Strip quotes from beginning and end of string
164
+ // This allows the alpha value to be present inside of quotes
165
+ path = path.replace(/^['"]+|['"]+$/g, '')
166
+
165
167
  let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/)
166
168
  let alpha = undefined
167
169
 
@@ -181,9 +183,15 @@ export default function ({ tailwindConfig: config }) {
181
183
  throw node.error(error)
182
184
  }
183
185
 
184
- if (alpha !== undefined) {
185
- value = parseColorFormat(value)
186
- value = withAlphaValue(value, alpha, value)
186
+ let maybeColor = parseColorFormat(value)
187
+ let isColorFunction = maybeColor !== undefined && typeof maybeColor === 'function'
188
+
189
+ if (alpha !== undefined || isColorFunction) {
190
+ if (alpha === undefined) {
191
+ alpha = 1.0
192
+ }
193
+
194
+ value = withAlphaValue(maybeColor, alpha, maybeColor)
187
195
  }
188
196
 
189
197
  return value
@@ -163,15 +163,17 @@ function applyVariant(variant, matches, context) {
163
163
 
164
164
  let container = postcss.root({ nodes: [rule.clone()] })
165
165
 
166
- for (let [variantSort, variantFunction] of variantFunctionTuples) {
167
- let clone = container.clone()
166
+ for (let [variantSort, variantFunction, containerFromArray] of variantFunctionTuples) {
167
+ let clone = containerFromArray ?? container.clone()
168
168
  let collectedFormats = []
169
169
 
170
- let originals = new Map()
171
-
172
170
  function prepareBackup() {
173
- if (originals.size > 0) return // Already prepared, chicken out
174
- clone.walkRules((rule) => originals.set(rule, rule.selector))
171
+ // Already prepared, chicken out
172
+ if (clone.raws.neededBackup) {
173
+ return
174
+ }
175
+ clone.raws.neededBackup = true
176
+ clone.walkRules((rule) => (rule.raws.originalSelector = rule.selector))
175
177
  }
176
178
 
177
179
  function modifySelectors(modifierFunction) {
@@ -231,6 +233,10 @@ function applyVariant(variant, matches, context) {
231
233
  // reserving additional X places for these 'unknown' variants in between.
232
234
  variantSort | BigInt(idx << ruleWithVariant.length),
233
235
  variantFunction,
236
+
237
+ // If the clone has been modified we have to pass that back
238
+ // though so each rule can use the modified container
239
+ clone.clone(),
234
240
  ])
235
241
  }
236
242
  continue
@@ -244,13 +250,15 @@ function applyVariant(variant, matches, context) {
244
250
  continue
245
251
  }
246
252
 
247
- // We filled the `originals`, therefore we assume that somebody touched
253
+ // We had to backup selectors, therefore we assume that somebody touched
248
254
  // `container` or `modifySelectors`. Let's see if they did, so that we
249
255
  // can restore the selectors, and collect the format strings.
250
- if (originals.size > 0) {
256
+ if (clone.raws.neededBackup) {
257
+ delete clone.raws.neededBackup
251
258
  clone.walkRules((rule) => {
252
- if (!originals.has(rule)) return
253
- let before = originals.get(rule)
259
+ let before = rule.raws.originalSelector
260
+ if (!before) return
261
+ delete rule.raws.originalSelector
254
262
  if (before === rule.selector) return // No mutation happened
255
263
 
256
264
  let modified = rule.selector
@@ -465,11 +465,14 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
465
465
  }
466
466
 
467
467
  if (Array.isArray(result)) {
468
- return result.map((variant) => parseVariant(variant))
468
+ return result
469
+ .filter((variant) => typeof variant === 'string')
470
+ .map((variant) => parseVariant(variant))
469
471
  }
470
472
 
471
473
  // result may be undefined with legacy variants that use APIs like `modifySelectors`
472
- return result && parseVariant(result)(api)
474
+ // result may also be a postcss node if someone was returning the result from `modifySelectors`
475
+ return result && typeof result === 'string' && parseVariant(result)(api)
473
476
  }
474
477
  }
475
478
 
@@ -40,18 +40,16 @@ export function normalize(value, isRoot = true) {
40
40
  value = value.trim()
41
41
  }
42
42
 
43
- // Add spaces around operators inside calc() that do not follow an operator
43
+ // Add spaces around operators inside math functions like calc() that do not follow an operator
44
44
  // or '('.
45
- value = value.replace(/calc\(.+\)/g, (match) => {
45
+ value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
46
46
  return match.replace(
47
47
  /(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g,
48
48
  '$1 $2 '
49
49
  )
50
50
  })
51
51
 
52
- // Add spaces around some operators not inside calc() that do not follow an operator
53
- // or '('.
54
- return value.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([\/])/g, '$1 $2 ')
52
+ return value
55
53
  }
56
54
 
57
55
  export function url(value) {
@@ -0,0 +1,24 @@
1
+ /**
2
+ * This function removes any uses of CSS variables used as an alpha channel
3
+ *
4
+ * This is required for selectors like `:visited` which do not allow
5
+ * changes in opacity or external control using CSS variables.
6
+ *
7
+ * @param {import('postcss').Container} container
8
+ * @param {string[]} toRemove
9
+ */
10
+ export function removeAlphaVariables(container, toRemove) {
11
+ container.walkDecls((decl) => {
12
+ if (toRemove.includes(decl.prop)) {
13
+ decl.remove()
14
+
15
+ return
16
+ }
17
+
18
+ for (let varName of toRemove) {
19
+ if (decl.value.includes(`/ var(${varName})`)) {
20
+ decl.value = decl.value.replace(`/ var(${varName})`, '')
21
+ }
22
+ }
23
+ })
24
+ }
package/types/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { CorePluginList } from './generated/CorePluginList'
1
+ import type { CorePluginList } from './generated/corePluginList'
2
2
  import type { DefaultColors } from './generated/colors'
3
3
 
4
4
  // Helpers