tailwindcss 0.0.0-insiders.bd970d0 → 0.0.0-insiders.bda8421

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.
Files changed (137) hide show
  1. package/README.md +1 -2
  2. package/lib/cli/build/deps.js +62 -0
  3. package/lib/cli/build/index.js +12 -15
  4. package/lib/cli/build/plugin.js +107 -167
  5. package/lib/cli/build/utils.js +13 -13
  6. package/lib/cli/build/watching.js +10 -10
  7. package/lib/cli/help/index.js +11 -11
  8. package/lib/cli/index.js +60 -61
  9. package/lib/cli/init/index.js +16 -16
  10. package/lib/cli-peer-dependencies.js +36 -0
  11. package/lib/cli.js +1 -1
  12. package/lib/corePluginList.js +4 -1
  13. package/lib/corePlugins.js +2018 -1905
  14. package/lib/css/preflight.css +18 -12
  15. package/lib/featureFlags.js +17 -23
  16. package/lib/index.js +1 -1
  17. package/lib/lib/cacheInvalidation.js +3 -3
  18. package/lib/lib/collapseAdjacentRules.js +6 -6
  19. package/lib/lib/collapseDuplicateDeclarations.js +1 -1
  20. package/lib/lib/content.js +39 -32
  21. package/lib/lib/defaultExtractor.js +40 -17
  22. package/lib/lib/evaluateTailwindFunctions.js +23 -23
  23. package/lib/lib/expandApplyAtRules.js +37 -18
  24. package/lib/lib/expandTailwindAtRules.js +49 -85
  25. package/lib/lib/findAtConfigPath.js +5 -5
  26. package/lib/lib/generateRules.js +82 -55
  27. package/lib/lib/getModuleDependencies.js +23 -23
  28. package/lib/lib/load-config.js +21 -6
  29. package/lib/lib/normalizeTailwindDirectives.js +36 -21
  30. package/lib/lib/offsets.js +97 -48
  31. package/lib/lib/partitionApplyAtRules.js +2 -2
  32. package/lib/lib/regex.js +5 -5
  33. package/lib/lib/resolveDefaultsAtRules.js +27 -25
  34. package/lib/lib/setupContextUtils.js +195 -167
  35. package/lib/lib/setupTrackingContext.js +4 -5
  36. package/lib/lib/sharedState.js +10 -10
  37. package/lib/lib/substituteScreenAtRules.js +4 -4
  38. package/lib/plugin.js +8 -124
  39. package/lib/postcss-plugins/nesting/index.js +2 -2
  40. package/lib/postcss-plugins/nesting/plugin.js +11 -11
  41. package/lib/processTailwindFeatures.js +3 -5
  42. package/lib/public/colors.js +264 -264
  43. package/lib/util/applyImportantSelector.js +2 -2
  44. package/lib/util/buildMediaQuery.js +2 -2
  45. package/lib/util/cloneDeep.js +1 -1
  46. package/lib/util/cloneNodes.js +33 -13
  47. package/lib/util/color.js +19 -19
  48. package/lib/util/createUtilityPlugin.js +3 -3
  49. package/lib/util/dataTypes.js +170 -113
  50. package/lib/util/defaults.js +4 -4
  51. package/lib/util/escapeClassName.js +2 -2
  52. package/lib/util/escapeCommas.js +1 -1
  53. package/lib/util/flattenColorPalette.js +2 -2
  54. package/lib/util/formatVariantSelector.js +24 -19
  55. package/lib/util/getAllConfigs.js +4 -5
  56. package/lib/util/isKeyframeRule.js +1 -1
  57. package/lib/util/isPlainObject.js +2 -2
  58. package/lib/util/isSyntacticallyValidPropertyValue.js +10 -10
  59. package/lib/util/log.js +6 -23
  60. package/lib/util/nameClass.js +4 -4
  61. package/lib/util/negateValue.js +8 -8
  62. package/lib/util/normalizeConfig.js +63 -94
  63. package/lib/util/normalizeScreens.js +18 -18
  64. package/lib/util/parseAnimationValue.js +38 -38
  65. package/lib/util/parseBoxShadowValue.js +18 -18
  66. package/lib/util/parseDependency.js +4 -4
  67. package/lib/util/parseGlob.js +4 -4
  68. package/lib/util/parseObjectStyles.js +1 -1
  69. package/lib/util/pluginUtils.js +36 -21
  70. package/lib/util/prefixSelector.js +4 -4
  71. package/lib/util/pseudoElements.js +72 -69
  72. package/lib/util/removeAlphaVariables.js +1 -1
  73. package/lib/util/resolveConfig.js +11 -15
  74. package/lib/util/resolveConfigPath.js +6 -6
  75. package/lib/util/responsive.js +1 -1
  76. package/lib/util/splitAtTopLevelOnly.js +3 -3
  77. package/lib/util/toColorValue.js +1 -1
  78. package/lib/util/toPath.js +2 -2
  79. package/lib/util/transformThemeValue.js +24 -24
  80. package/lib/util/validateConfig.js +9 -20
  81. package/lib/util/validateFormalSyntax.js +5 -5
  82. package/lib/util/withAlphaVariable.js +5 -5
  83. package/lib/value-parser/index.js +5 -5
  84. package/lib/value-parser/parse.js +43 -43
  85. package/lib/value-parser/stringify.js +11 -11
  86. package/lib/value-parser/unit.js +5 -5
  87. package/lib/value-parser/walk.js +1 -1
  88. package/nesting/index.d.ts +4 -0
  89. package/package.json +41 -36
  90. package/peers/index.js +96503 -0
  91. package/resolveConfig.d.ts +22 -3
  92. package/scripts/generate-types.js +1 -2
  93. package/scripts/release-notes.js +1 -1
  94. package/src/cli/build/deps.js +56 -0
  95. package/src/cli/build/index.js +0 -4
  96. package/src/cli/build/plugin.js +53 -85
  97. package/src/cli/build/watching.js +1 -1
  98. package/src/cli/index.js +0 -1
  99. package/src/cli-peer-dependencies.js +15 -0
  100. package/src/corePluginList.js +1 -1
  101. package/src/corePlugins.js +118 -31
  102. package/src/css/preflight.css +18 -12
  103. package/src/featureFlags.js +3 -5
  104. package/src/lib/content.js +39 -30
  105. package/src/lib/defaultExtractor.js +29 -6
  106. package/src/lib/expandApplyAtRules.js +24 -0
  107. package/src/lib/expandTailwindAtRules.js +19 -56
  108. package/src/lib/generateRules.js +39 -8
  109. package/src/lib/load-config.ts +13 -0
  110. package/src/lib/normalizeTailwindDirectives.js +27 -0
  111. package/src/lib/offsets.js +62 -3
  112. package/src/lib/resolveDefaultsAtRules.js +5 -1
  113. package/src/lib/setupContextUtils.js +79 -39
  114. package/src/plugin.js +0 -86
  115. package/src/processTailwindFeatures.js +0 -3
  116. package/src/util/cloneNodes.js +35 -14
  117. package/src/util/dataTypes.js +72 -6
  118. package/src/util/formatVariantSelector.js +7 -0
  119. package/src/util/isPlainObject.js +1 -1
  120. package/src/util/log.js +0 -24
  121. package/src/util/normalizeConfig.js +11 -38
  122. package/src/util/pluginUtils.js +20 -0
  123. package/src/util/pseudoElements.js +4 -0
  124. package/src/util/validateConfig.js +0 -10
  125. package/stubs/config.full.js +68 -8
  126. package/stubs/config.simple.js +1 -1
  127. package/stubs/postcss.config.cjs +1 -0
  128. package/stubs/postcss.config.js +1 -0
  129. package/types/config.d.ts +12 -5
  130. package/types/generated/corePluginList.d.ts +1 -1
  131. package/types/generated/default-theme.d.ts +28 -9
  132. package/types/index.d.ts +7 -3
  133. package/index.css +0 -5
  134. package/lib/lib/detectNesting.js +0 -45
  135. package/lib/lib/handleImportAtRules.js +0 -50
  136. package/src/lib/detectNesting.js +0 -47
  137. package/src/lib/handleImportAtRules.js +0 -34
package/src/plugin.js CHANGED
@@ -1,16 +1,7 @@
1
- import postcss from 'postcss'
2
- import lightningcss, { Features } from 'lightningcss'
3
- import browserslist from 'browserslist'
4
1
  import setupTrackingContext from './lib/setupTrackingContext'
5
2
  import processTailwindFeatures from './processTailwindFeatures'
6
3
  import { env } from './lib/sharedState'
7
4
  import { findAtConfigPath } from './lib/findAtConfigPath'
8
- import { handleImportAtRules } from './lib/handleImportAtRules'
9
- import { version as tailwindVersion } from '../package.json'
10
-
11
- function license() {
12
- return `/* ! tailwindcss v${tailwindVersion} | MIT License | https://tailwindcss.com */\n`
13
- }
14
5
 
15
6
  module.exports = function tailwindcss(configOrPath) {
16
7
  return {
@@ -22,7 +13,6 @@ module.exports = function tailwindcss(configOrPath) {
22
13
  console.time('JIT TOTAL')
23
14
  return root
24
15
  },
25
- ...handleImportAtRules(),
26
16
  async function (root, result) {
27
17
  // Use the path for the `@config` directive if it exists, otherwise use the
28
18
  // path for the file being processed
@@ -44,82 +34,6 @@ module.exports = function tailwindcss(configOrPath) {
44
34
 
45
35
  await processTailwindFeatures(context)(root, result)
46
36
  },
47
- function lightningCssPlugin(_root, result) {
48
- let map = result.map ?? result.opts.map
49
-
50
- let intermediateResult = result.root.toResult({
51
- map: map ? { inline: true } : false,
52
- })
53
-
54
- let intermediateMap = intermediateResult.map?.toJSON?.() ?? map
55
-
56
- try {
57
- let resolvedBrowsersListConfig = browserslist.findConfig(
58
- result.opts.from ?? process.cwd()
59
- )?.defaults
60
- let defaultBrowsersListConfig = require('../package.json').browserslist
61
- let browsersListConfig = resolvedBrowsersListConfig ?? defaultBrowsersListConfig
62
-
63
- let transformed = lightningcss.transform({
64
- filename: result.opts.from,
65
- code: Buffer.from(intermediateResult.css),
66
- minify: false,
67
- sourceMap: !!intermediateMap,
68
- targets: lightningcss.browserslistToTargets(browserslist(browsersListConfig)),
69
- drafts: {
70
- nesting: true,
71
- customMedia: true,
72
- },
73
- nonStandard: {
74
- deepSelectorCombinator: true,
75
- },
76
- include: Features.Nesting,
77
- exclude: Features.LogicalProperties,
78
- })
79
-
80
- let code = transformed.code.toString()
81
-
82
- // https://postcss.org/api/#sourcemapoptions
83
- if (intermediateMap && transformed.map != null) {
84
- let prev = transformed.map.toString()
85
-
86
- if (typeof intermediateMap === 'object') {
87
- intermediateMap.prev = prev
88
- } else {
89
- code = `${code}\n/*# sourceMappingURL=data:application/json;base64,${Buffer.from(
90
- prev
91
- ).toString('base64')} */`
92
- }
93
- }
94
-
95
- result.root = postcss.parse(license() + code, {
96
- ...result.opts,
97
- map: intermediateMap,
98
- })
99
- } catch (err) {
100
- if (err.source && typeof process !== 'undefined' && process.env.JEST_WORKER_ID) {
101
- let lines = err.source.split('\n')
102
- err = new Error(
103
- [
104
- 'Error formatting using Lightning CSS:',
105
- '',
106
- ...[
107
- '```css',
108
- ...lines.slice(Math.max(err.loc.line - 3, 0), err.loc.line),
109
- ' '.repeat(err.loc.column - 1) + '^-- ' + err.toString(),
110
- ...lines.slice(err.loc.line, err.loc.line + 2),
111
- '```',
112
- ],
113
- ].join('\n')
114
- )
115
- }
116
-
117
- if (Error.captureStackTrace) {
118
- Error.captureStackTrace(err, lightningCssPlugin)
119
- }
120
- throw err
121
- }
122
- },
123
37
  env.DEBUG &&
124
38
  function (root) {
125
39
  console.timeEnd('JIT TOTAL')
@@ -7,7 +7,6 @@ import resolveDefaultsAtRules from './lib/resolveDefaultsAtRules'
7
7
  import collapseAdjacentRules from './lib/collapseAdjacentRules'
8
8
  import collapseDuplicateDeclarations from './lib/collapseDuplicateDeclarations'
9
9
  import partitionApplyAtRules from './lib/partitionApplyAtRules'
10
- import detectNesting from './lib/detectNesting'
11
10
  import { createContext } from './lib/setupContextUtils'
12
11
  import { issueFlagNotices } from './featureFlags'
13
12
 
@@ -15,8 +14,6 @@ export default function processTailwindFeatures(setupContext) {
15
14
  return async function (root, result) {
16
15
  let { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root)
17
16
 
18
- detectNesting()(root, result)
19
-
20
17
  // Partition apply rules that are found in the css
21
18
  // itself.
22
19
  partitionApplyAtRules()(root, result)
@@ -1,21 +1,13 @@
1
+ /**
2
+ * @param {import('postcss').Container[]} nodes
3
+ * @param {any} source
4
+ * @param {any} raws
5
+ * @returns {import('postcss').Container[]}
6
+ */
1
7
  export default function cloneNodes(nodes, source = undefined, raws = undefined) {
2
8
  return nodes.map((node) => {
3
9
  let cloned = node.clone()
4
10
 
5
- // We always want override the source map
6
- // except when explicitly told not to
7
- let shouldOverwriteSource = node.raws.tailwind?.preserveSource !== true || !cloned.source
8
-
9
- if (source !== undefined && shouldOverwriteSource) {
10
- cloned.source = source
11
-
12
- if ('walk' in cloned) {
13
- cloned.walk((child) => {
14
- child.source = source
15
- })
16
- }
17
- }
18
-
19
11
  if (raws !== undefined) {
20
12
  cloned.raws.tailwind = {
21
13
  ...cloned.raws.tailwind,
@@ -23,6 +15,35 @@ export default function cloneNodes(nodes, source = undefined, raws = undefined)
23
15
  }
24
16
  }
25
17
 
18
+ if (source !== undefined) {
19
+ traverse(cloned, (node) => {
20
+ // Do not traverse nodes that have opted
21
+ // to preserve their original source
22
+ let shouldPreserveSource = node.raws.tailwind?.preserveSource === true && node.source
23
+ if (shouldPreserveSource) {
24
+ return false
25
+ }
26
+
27
+ // Otherwise we can safely replace the source
28
+ // And continue traversing
29
+ node.source = source
30
+ })
31
+ }
32
+
26
33
  return cloned
27
34
  })
28
35
  }
36
+
37
+ /**
38
+ * Traverse a tree of nodes and don't traverse children if the callback
39
+ * returns false. Ideally we'd use Container#walk instead of this
40
+ * function but it stops traversing siblings too.
41
+ *
42
+ * @param {import('postcss').Container} node
43
+ * @param {(node: import('postcss').Container) => boolean} onNode
44
+ */
45
+ function traverse(node, onNode) {
46
+ if (onNode(node) !== false) {
47
+ node.each?.((child) => traverse(child, onNode))
48
+ }
49
+ }
@@ -10,10 +10,34 @@ function isCSSFunction(value) {
10
10
  return cssFunctions.some((fn) => new RegExp(`^${fn}\\(.*\\)`).test(value))
11
11
  }
12
12
 
13
+ // These properties accept a `<dashed-ident>` as one of the values. This means that you can use them
14
+ // as: `timeline-scope: --tl;`
15
+ //
16
+ // Without the `var(--tl)`, in these cases we don't want to normalize the value, and you should add
17
+ // the `var()` yourself.
18
+ //
19
+ // More info:
20
+ // - https://drafts.csswg.org/scroll-animations/#propdef-timeline-scope
21
+ // - https://developer.mozilla.org/en-US/docs/Web/CSS/timeline-scope#dashed-ident
22
+ //
23
+ const AUTO_VAR_INJECTION_EXCEPTIONS = new Set([
24
+ // Concrete properties
25
+ 'scroll-timeline-name',
26
+ 'timeline-scope',
27
+ 'view-timeline-name',
28
+ 'font-palette',
29
+
30
+ // Shorthand properties
31
+ 'scroll-timeline',
32
+ 'animation-timeline',
33
+ 'view-timeline',
34
+ ])
35
+
13
36
  // This is not a data type, but rather a function that can normalize the
14
37
  // correct values.
15
- export function normalize(value, isRoot = true) {
16
- if (value.startsWith('--')) {
38
+ export function normalize(value, context = null, isRoot = true) {
39
+ let isVarException = context && AUTO_VAR_INJECTION_EXCEPTIONS.has(context.property)
40
+ if (value.startsWith('--') && !isVarException) {
17
41
  return `var(${value})`
18
42
  }
19
43
 
@@ -27,7 +51,7 @@ export function normalize(value, isRoot = true) {
27
51
  return part
28
52
  }
29
53
 
30
- return normalize(part, false)
54
+ return normalize(part, context, false)
31
55
  })
32
56
  .join('')
33
57
  }
@@ -53,13 +77,43 @@ export function normalize(value, isRoot = true) {
53
77
 
54
78
  /**
55
79
  * Add spaces around operators inside math functions
56
- * like calc() that do not follow an operator or '('.
80
+ * like calc() that do not follow an operator, '(', or `,`.
57
81
  *
58
82
  * @param {string} value
59
83
  * @returns {string}
60
84
  */
61
85
  function normalizeMathOperatorSpacing(value) {
62
86
  let preventFormattingInFunctions = ['theme']
87
+ let preventFormattingKeywords = [
88
+ 'min-content',
89
+ 'max-content',
90
+ 'fit-content',
91
+
92
+ // Env
93
+ 'safe-area-inset-top',
94
+ 'safe-area-inset-right',
95
+ 'safe-area-inset-bottom',
96
+ 'safe-area-inset-left',
97
+
98
+ 'titlebar-area-x',
99
+ 'titlebar-area-y',
100
+ 'titlebar-area-width',
101
+ 'titlebar-area-height',
102
+
103
+ 'keyboard-inset-top',
104
+ 'keyboard-inset-right',
105
+ 'keyboard-inset-bottom',
106
+ 'keyboard-inset-left',
107
+ 'keyboard-inset-width',
108
+ 'keyboard-inset-height',
109
+
110
+ 'radial-gradient',
111
+ 'linear-gradient',
112
+ 'conic-gradient',
113
+ 'repeating-radial-gradient',
114
+ 'repeating-linear-gradient',
115
+ 'repeating-conic-gradient',
116
+ ]
63
117
 
64
118
  return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
65
119
  let result = ''
@@ -102,15 +156,27 @@ function normalizeMathOperatorSpacing(value) {
102
156
  result += consumeUntil([')', ','])
103
157
  }
104
158
 
159
+ // Skip formatting of known keywords
160
+ else if (preventFormattingKeywords.some((keyword) => peek(keyword))) {
161
+ let keyword = preventFormattingKeywords.find((keyword) => peek(keyword))
162
+ result += keyword
163
+ i += keyword.length - 1
164
+ }
165
+
105
166
  // Skip formatting inside known functions
106
167
  else if (preventFormattingInFunctions.some((fn) => peek(fn))) {
107
168
  result += consumeUntil([')'])
108
169
  }
109
170
 
171
+ // Don't break CSS grid track names
172
+ else if (peek('[')) {
173
+ result += consumeUntil([']'])
174
+ }
175
+
110
176
  // Handle operators
111
177
  else if (
112
178
  ['+', '-', '*', '/'].includes(char) &&
113
- !['(', '+', '-', '*', '/'].includes(lastChar())
179
+ !['(', '+', '-', '*', '/', ','].includes(lastChar())
114
180
  ) {
115
181
  result += ` ${char} `
116
182
  } else {
@@ -327,7 +393,7 @@ let absoluteSizes = new Set([
327
393
  'medium',
328
394
  'large',
329
395
  'x-large',
330
- 'x-large',
396
+ 'xx-large',
331
397
  'xxx-large',
332
398
  ])
333
399
  export function absoluteSize(value) {
@@ -186,6 +186,13 @@ export function finalizeSelector(current, formats, { context, candidate, base })
186
186
  // Remove extraneous selectors that do not include the base candidate
187
187
  selector.each((sel) => eliminateIrrelevantSelectors(sel, base))
188
188
 
189
+ // If ffter eliminating irrelevant selectors, we end up with nothing
190
+ // Then the whole "rule" this is associated with does not need to exist
191
+ // We use `null` as a marker value for that case
192
+ if (selector.length === 0) {
193
+ return null
194
+ }
195
+
189
196
  // If there are no formats that means there were no variants added to the candidate
190
197
  // so we can just return the selector as-is
191
198
  let formatAst = Array.isArray(formats)
@@ -4,5 +4,5 @@ export default function isPlainObject(value) {
4
4
  }
5
5
 
6
6
  const prototype = Object.getPrototypeOf(value)
7
- return prototype === null || prototype === Object.prototype
7
+ return prototype === null || Object.getPrototypeOf(prototype) === null
8
8
  }
package/src/util/log.js CHANGED
@@ -17,30 +17,6 @@ export function dim(input) {
17
17
  }
18
18
 
19
19
  export default {
20
- group(key, cb) {
21
- if (typeof process !== 'undefined' && process.env.JEST_WORKER_ID) return
22
-
23
- if (key && alreadyShown.has(key)) return
24
- if (key) alreadyShown.add(key)
25
-
26
- console.warn('')
27
-
28
- cb({
29
- info(messages) {
30
- messages.forEach((message) => console.warn(colors.bold(colors.cyan('info')), '-', message))
31
- },
32
- warn(messages) {
33
- messages.forEach((message) =>
34
- console.warn(colors.bold(colors.yellow('warn')), '-', message)
35
- )
36
- },
37
- risk(messages) {
38
- messages.forEach((message) =>
39
- console.warn(colors.bold(colors.magenta('risk')), '-', message)
40
- )
41
- },
42
- })
43
- },
44
20
  info(key, messages) {
45
21
  log(colors.bold(colors.cyan('info')), ...(Array.isArray(key) ? [key] : [messages, key]))
46
22
  },
@@ -1,4 +1,4 @@
1
- import { flagEnabled, featureFlags } from '../featureFlags'
1
+ import { flagEnabled } from '../featureFlags'
2
2
  import log, { dim } from './log'
3
3
 
4
4
  export function normalizeConfig(config) {
@@ -18,10 +18,6 @@ export function normalizeConfig(config) {
18
18
  * }
19
19
  */
20
20
  let valid = (() => {
21
- if (config.content === 'auto') {
22
- return true
23
- }
24
-
25
21
  // `config.purge` should not exist anymore
26
22
  if (config.purge) {
27
23
  return false
@@ -200,17 +196,11 @@ export function normalizeConfig(config) {
200
196
  files: (() => {
201
197
  let { content, purge } = config
202
198
 
203
- if (content === undefined && purge === undefined) return []
204
- if (purge) {
205
- if (Array.isArray(purge)) return purge
206
- if (Array.isArray(purge?.content)) return purge.content
207
- return []
208
- }
209
-
199
+ if (Array.isArray(purge)) return purge
200
+ if (Array.isArray(purge?.content)) return purge.content
210
201
  if (Array.isArray(content)) return content
211
202
  if (Array.isArray(content?.content)) return content.content
212
203
  if (Array.isArray(content?.files)) return content.files
213
- if (content === 'auto') return ['auto']
214
204
 
215
205
  return []
216
206
  })(),
@@ -294,33 +284,16 @@ export function normalizeConfig(config) {
294
284
  })(),
295
285
  }
296
286
 
297
- // Force disable the `oxideParser` feature flag when using unsupported features.
298
- // TODO: Remove once we have prefix or separator support in the oxide parser.
299
- if (config.prefix !== '' || config.separator !== ':') {
300
- if (config.experimental === 'all') {
301
- config.experimental = {}
302
- for (let key of featureFlags.experimental) {
303
- config.experimental[key] = true
304
- }
305
- } else {
306
- config.experimental = config.experimental ?? {}
307
- }
308
-
309
- config.experimental.oxideParser = false
310
- }
311
-
312
287
  // Validate globs to prevent bogus globs.
313
288
  // E.g.: `./src/*.{html}` is invalid, the `{html}` should just be `html`
314
- if (config.content.files !== 'auto') {
315
- for (let file of config.content.files) {
316
- if (typeof file === 'string' && /{([^,]*?)}/g.test(file)) {
317
- log.warn('invalid-glob-braces', [
318
- `The glob pattern ${dim(file)} in your Tailwind CSS configuration is invalid.`,
319
- `Update it to ${dim(file.replace(/{([^,]*?)}/g, '$1'))} to silence this warning.`,
320
- // TODO: Add https://tw.wtf/invalid-glob-braces
321
- ])
322
- break
323
- }
289
+ for (let file of config.content.files) {
290
+ if (typeof file === 'string' && /{([^,]*?)}/g.test(file)) {
291
+ log.warn('invalid-glob-braces', [
292
+ `The glob pattern ${dim(file)} in your Tailwind CSS configuration is invalid.`,
293
+ `Update it to ${dim(file.replace(/{([^,]*?)}/g, '$1'))} to silence this warning.`,
294
+ // TODO: Add https://tw.wtf/invalid-glob-braces
295
+ ])
296
+ break
324
297
  }
325
298
  }
326
299
 
@@ -18,6 +18,7 @@ import {
18
18
  } from './dataTypes'
19
19
  import negateValue from './negateValue'
20
20
  import { backgroundSize } from './validateFormalSyntax'
21
+ import { flagEnabled } from '../featureFlags.js'
21
22
 
22
23
  /**
23
24
  * @param {import('postcss-selector-parser').Container} selectors
@@ -87,6 +88,22 @@ function isArbitraryValue(input) {
87
88
  function splitUtilityModifier(modifier) {
88
89
  let slashIdx = modifier.lastIndexOf('/')
89
90
 
91
+ // If the `/` is inside an arbitrary, we want to find the previous one if any
92
+ // This logic probably isn't perfect but it should work for most cases
93
+ let arbitraryStartIdx = modifier.lastIndexOf('[', slashIdx)
94
+ let arbitraryEndIdx = modifier.indexOf(']', slashIdx)
95
+
96
+ let isNextToArbitrary = modifier[slashIdx - 1] === ']' || modifier[slashIdx + 1] === '['
97
+
98
+ // Backtrack to the previous `/` if the one we found was inside an arbitrary
99
+ if (!isNextToArbitrary) {
100
+ if (arbitraryStartIdx !== -1 && arbitraryEndIdx !== -1) {
101
+ if (arbitraryStartIdx < slashIdx && slashIdx < arbitraryEndIdx) {
102
+ slashIdx = modifier.lastIndexOf('/', arbitraryStartIdx)
103
+ }
104
+ }
105
+ }
106
+
90
107
  if (slashIdx === -1 || slashIdx === modifier.length - 1) {
91
108
  return [modifier, undefined]
92
109
  }
@@ -242,9 +259,12 @@ export function coerceValue(types, modifier, options, tailwindConfig) {
242
259
  * @returns {Iterator<[value: string, type: string, modifier: string | null]>}
243
260
  */
244
261
  export function* getMatchingTypes(types, rawModifier, options, tailwindConfig) {
262
+ let modifiersEnabled = flagEnabled(tailwindConfig, 'generalizedModifiers')
263
+
245
264
  let [modifier, utilityModifier] = splitUtilityModifier(rawModifier)
246
265
 
247
266
  let canUseUtilityModifier =
267
+ modifiersEnabled &&
248
268
  options.modifiers != null &&
249
269
  (options.modifiers === 'any' ||
250
270
  (typeof options.modifiers === 'object' &&
@@ -60,6 +60,10 @@ let elementProperties = {
60
60
  ':first-letter': ['terminal', 'jumpable'],
61
61
  ':first-line': ['terminal', 'jumpable'],
62
62
 
63
+ ':where': [],
64
+ ':is': [],
65
+ ':has': [],
66
+
63
67
  // The default value is used when the pseudo-element is not recognized
64
68
  // Because it's not recognized, we don't know if it's terminal or not
65
69
  // So we assume it can be moved AND can have user-action pseudo classes attached to it
@@ -1,4 +1,3 @@
1
- import pc from 'picocolors'
2
1
  import log from './log'
3
2
 
4
3
  export function validateConfig(config) {
@@ -10,15 +9,6 @@ export function validateConfig(config) {
10
9
  ])
11
10
  }
12
11
 
13
- if (config.content.files.includes('auto')) {
14
- log.group('auto-content-experimental', (log) => {
15
- log.info([pc.bold('Automatically detecting Tailwind CSS content sources...')])
16
- log.warn([
17
- 'Automatic content detection is experimental, and the behavior may change at any time.',
18
- ])
19
- })
20
- }
21
-
22
12
  // Warn if the line-clamp plugin is installed
23
13
  try {
24
14
  let plugin = require('@tailwindcss/line-clamp')
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
- content: ['auto'],
2
+ content: [],
3
3
  presets: [],
4
4
  darkMode: 'media', // or 'class'
5
5
  theme: {
@@ -444,6 +444,12 @@ module.exports = {
444
444
  'span-4': 'span 4 / span 4',
445
445
  'span-5': 'span 5 / span 5',
446
446
  'span-6': 'span 6 / span 6',
447
+ 'span-7': 'span 7 / span 7',
448
+ 'span-8': 'span 8 / span 8',
449
+ 'span-9': 'span 9 / span 9',
450
+ 'span-10': 'span 10 / span 10',
451
+ 'span-11': 'span 11 / span 11',
452
+ 'span-12': 'span 12 / span 12',
447
453
  'span-full': '1 / -1',
448
454
  },
449
455
  gridRowEnd: {
@@ -455,6 +461,12 @@ module.exports = {
455
461
  5: '5',
456
462
  6: '6',
457
463
  7: '7',
464
+ 8: '8',
465
+ 9: '9',
466
+ 10: '10',
467
+ 11: '11',
468
+ 12: '12',
469
+ 13: '13',
458
470
  },
459
471
  gridRowStart: {
460
472
  auto: 'auto',
@@ -465,9 +477,16 @@ module.exports = {
465
477
  5: '5',
466
478
  6: '6',
467
479
  7: '7',
480
+ 8: '8',
481
+ 9: '9',
482
+ 10: '10',
483
+ 11: '11',
484
+ 12: '12',
485
+ 13: '13',
468
486
  },
469
487
  gridTemplateColumns: {
470
488
  none: 'none',
489
+ subgrid: 'subgrid',
471
490
  1: 'repeat(1, minmax(0, 1fr))',
472
491
  2: 'repeat(2, minmax(0, 1fr))',
473
492
  3: 'repeat(3, minmax(0, 1fr))',
@@ -483,12 +502,19 @@ module.exports = {
483
502
  },
484
503
  gridTemplateRows: {
485
504
  none: 'none',
505
+ subgrid: 'subgrid',
486
506
  1: 'repeat(1, minmax(0, 1fr))',
487
507
  2: 'repeat(2, minmax(0, 1fr))',
488
508
  3: 'repeat(3, minmax(0, 1fr))',
489
509
  4: 'repeat(4, minmax(0, 1fr))',
490
510
  5: 'repeat(5, minmax(0, 1fr))',
491
511
  6: 'repeat(6, minmax(0, 1fr))',
512
+ 7: 'repeat(7, minmax(0, 1fr))',
513
+ 8: 'repeat(8, minmax(0, 1fr))',
514
+ 9: 'repeat(9, minmax(0, 1fr))',
515
+ 10: 'repeat(10, minmax(0, 1fr))',
516
+ 11: 'repeat(11, minmax(0, 1fr))',
517
+ 12: 'repeat(12, minmax(0, 1fr))',
492
518
  },
493
519
  height: ({ theme }) => ({
494
520
  auto: 'auto',
@@ -625,8 +651,8 @@ module.exports = {
625
651
  fit: 'fit-content',
626
652
  }),
627
653
  maxWidth: ({ theme, breakpoints }) => ({
654
+ ...theme('spacing'),
628
655
  none: 'none',
629
- 0: '0rem',
630
656
  xs: '20rem',
631
657
  sm: '24rem',
632
658
  md: '28rem',
@@ -645,8 +671,8 @@ module.exports = {
645
671
  prose: '65ch',
646
672
  ...breakpoints(theme('screens')),
647
673
  }),
648
- minHeight: {
649
- 0: '0px',
674
+ minHeight: ({ theme }) => ({
675
+ ...theme('spacing'),
650
676
  full: '100%',
651
677
  screen: '100vh',
652
678
  svh: '100svh',
@@ -655,14 +681,14 @@ module.exports = {
655
681
  min: 'min-content',
656
682
  max: 'max-content',
657
683
  fit: 'fit-content',
658
- },
659
- minWidth: {
660
- 0: '0px',
684
+ }),
685
+ minWidth: ({ theme }) => ({
686
+ ...theme('spacing'),
661
687
  full: '100%',
662
688
  min: 'min-content',
663
689
  max: 'max-content',
664
690
  fit: 'fit-content',
665
- },
691
+ }),
666
692
  objectPosition: {
667
693
  bottom: 'bottom',
668
694
  center: 'center',
@@ -944,6 +970,40 @@ module.exports = {
944
970
  '3/4': '75%',
945
971
  full: '100%',
946
972
  }),
973
+ size: ({ theme }) => ({
974
+ auto: 'auto',
975
+ ...theme('spacing'),
976
+ '1/2': '50%',
977
+ '1/3': '33.333333%',
978
+ '2/3': '66.666667%',
979
+ '1/4': '25%',
980
+ '2/4': '50%',
981
+ '3/4': '75%',
982
+ '1/5': '20%',
983
+ '2/5': '40%',
984
+ '3/5': '60%',
985
+ '4/5': '80%',
986
+ '1/6': '16.666667%',
987
+ '2/6': '33.333333%',
988
+ '3/6': '50%',
989
+ '4/6': '66.666667%',
990
+ '5/6': '83.333333%',
991
+ '1/12': '8.333333%',
992
+ '2/12': '16.666667%',
993
+ '3/12': '25%',
994
+ '4/12': '33.333333%',
995
+ '5/12': '41.666667%',
996
+ '6/12': '50%',
997
+ '7/12': '58.333333%',
998
+ '8/12': '66.666667%',
999
+ '9/12': '75%',
1000
+ '10/12': '83.333333%',
1001
+ '11/12': '91.666667%',
1002
+ full: '100%',
1003
+ min: 'min-content',
1004
+ max: 'max-content',
1005
+ fit: 'fit-content',
1006
+ }),
947
1007
  width: ({ theme }) => ({
948
1008
  auto: 'auto',
949
1009
  ...theme('spacing'),
@@ -1,5 +1,5 @@
1
1
  module.exports = {
2
- content: ['auto'],
2
+ content: [],
3
3
  theme: {
4
4
  extend: {},
5
5
  },