tailwindcss 3.0.21 → 3.0.24

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 (89) hide show
  1. package/CHANGELOG.md +45 -2
  2. package/lib/cli-peer-dependencies.js +3 -3
  3. package/lib/cli.js +183 -161
  4. package/lib/constants.js +8 -8
  5. package/lib/corePlugins.js +1597 -1518
  6. package/lib/featureFlags.js +9 -9
  7. package/lib/index.js +19 -6
  8. package/lib/lib/cacheInvalidation.js +69 -0
  9. package/lib/lib/collapseAdjacentRules.js +26 -13
  10. package/lib/lib/collapseDuplicateDeclarations.js +1 -1
  11. package/lib/lib/defaultExtractor.js +8 -6
  12. package/lib/lib/detectNesting.js +9 -9
  13. package/lib/lib/evaluateTailwindFunctions.js +16 -16
  14. package/lib/lib/expandApplyAtRules.js +180 -27
  15. package/lib/lib/expandTailwindAtRules.js +132 -122
  16. package/lib/lib/generateRules.js +117 -72
  17. package/lib/lib/getModuleDependencies.js +14 -14
  18. package/lib/lib/normalizeTailwindDirectives.js +35 -35
  19. package/lib/lib/partitionApplyAtRules.js +7 -7
  20. package/lib/lib/resolveDefaultsAtRules.js +81 -77
  21. package/lib/lib/setupContextUtils.js +83 -98
  22. package/lib/lib/setupTrackingContext.js +57 -57
  23. package/lib/lib/sharedState.js +11 -7
  24. package/lib/lib/substituteScreenAtRules.js +2 -2
  25. package/lib/postcss-plugins/nesting/README.md +2 -2
  26. package/lib/postcss-plugins/nesting/index.js +1 -1
  27. package/lib/postcss-plugins/nesting/plugin.js +41 -9
  28. package/lib/processTailwindFeatures.js +7 -7
  29. package/lib/public/colors.js +241 -241
  30. package/lib/public/resolve-config.js +5 -5
  31. package/lib/util/buildMediaQuery.js +2 -2
  32. package/lib/util/cloneDeep.js +1 -1
  33. package/lib/util/cloneNodes.js +12 -1
  34. package/lib/util/color.js +21 -20
  35. package/lib/util/createUtilityPlugin.js +6 -6
  36. package/lib/util/dataTypes.js +77 -75
  37. package/lib/util/escapeClassName.js +5 -5
  38. package/lib/util/escapeCommas.js +1 -1
  39. package/lib/util/flattenColorPalette.js +2 -2
  40. package/lib/util/formatVariantSelector.js +19 -19
  41. package/lib/util/getAllConfigs.js +5 -5
  42. package/lib/util/hashConfig.js +5 -5
  43. package/lib/util/isKeyframeRule.js +1 -1
  44. package/lib/util/isPlainObject.js +1 -1
  45. package/lib/util/isValidArbitraryValue.js +27 -27
  46. package/lib/util/log.js +8 -8
  47. package/lib/util/nameClass.js +7 -7
  48. package/lib/util/negateValue.js +4 -4
  49. package/lib/util/normalizeConfig.js +39 -39
  50. package/lib/util/normalizeScreens.js +4 -4
  51. package/lib/util/parseAnimationValue.js +56 -56
  52. package/lib/util/parseBoxShadowValue.js +60 -20
  53. package/lib/util/parseDependency.js +32 -32
  54. package/lib/util/parseObjectStyles.js +6 -6
  55. package/lib/util/pluginUtils.js +9 -9
  56. package/lib/util/prefixSelector.js +1 -1
  57. package/lib/util/resolveConfig.js +28 -28
  58. package/lib/util/resolveConfigPath.js +16 -16
  59. package/lib/util/responsive.js +6 -6
  60. package/lib/util/toColorValue.js +1 -1
  61. package/lib/util/toPath.js +2 -2
  62. package/lib/util/transformThemeValue.js +27 -27
  63. package/lib/util/withAlphaVariable.js +19 -19
  64. package/package.json +26 -25
  65. package/peers/index.js +4803 -4857
  66. package/scripts/generate-types.js +52 -0
  67. package/src/cli.js +41 -11
  68. package/src/corePlugins.js +104 -9
  69. package/src/featureFlags.js +2 -2
  70. package/src/index.js +17 -1
  71. package/src/lib/cacheInvalidation.js +52 -0
  72. package/src/lib/collapseAdjacentRules.js +16 -1
  73. package/src/lib/defaultExtractor.js +6 -4
  74. package/src/lib/expandApplyAtRules.js +179 -6
  75. package/src/lib/expandTailwindAtRules.js +26 -6
  76. package/src/lib/generateRules.js +73 -46
  77. package/src/lib/resolveDefaultsAtRules.js +6 -2
  78. package/src/lib/setupContextUtils.js +39 -48
  79. package/src/lib/setupTrackingContext.js +3 -3
  80. package/src/lib/sharedState.js +2 -0
  81. package/src/postcss-plugins/nesting/README.md +2 -2
  82. package/src/postcss-plugins/nesting/plugin.js +36 -0
  83. package/src/util/cloneNodes.js +14 -1
  84. package/src/util/color.js +7 -5
  85. package/src/util/dataTypes.js +3 -1
  86. package/src/util/log.js +7 -7
  87. package/src/util/parseBoxShadowValue.js +50 -2
  88. package/src/util/resolveConfig.js +32 -0
  89. package/stubs/defaultConfig.stub.js +5 -0
@@ -0,0 +1,52 @@
1
+ import prettier from 'prettier'
2
+ import { corePlugins } from '../src/corePlugins'
3
+ import colors from '../src/public/colors'
4
+ import fs from 'fs'
5
+ import path from 'path'
6
+
7
+ fs.writeFileSync(
8
+ path.join(process.cwd(), 'types', 'generated', 'corePluginList.d.ts'),
9
+ `export type CorePluginList = ${Object.keys(corePlugins)
10
+ .map((p) => `'${p}'`)
11
+ .join(' | ')}`
12
+ )
13
+
14
+ let colorsWithoutDeprecatedColors = Object.fromEntries(
15
+ Object.entries(Object.getOwnPropertyDescriptors(colors))
16
+ .filter(([_, { value }]) => {
17
+ return typeof value !== 'undefined'
18
+ })
19
+ .map(([name, definition]) => [name, definition.value])
20
+ )
21
+
22
+ let deprecatedColors = Object.entries(Object.getOwnPropertyDescriptors(colors))
23
+ .filter(([_, { value }]) => {
24
+ return typeof value === 'undefined'
25
+ })
26
+ .map(([name, definition]) => {
27
+ let warn = console.warn
28
+ let messages = []
29
+ console.warn = (...args) => messages.push(args.pop())
30
+ definition.get()
31
+ console.warn = warn
32
+ let message = messages.join(' ').trim()
33
+ let newColor = message.match(/renamed to `(.*)`/)[1]
34
+ return `/** @deprecated ${message} */${name}: DefaultColors['${newColor}'],`
35
+ })
36
+ .join('\n')
37
+
38
+ fs.writeFileSync(
39
+ path.join(process.cwd(), 'types', 'generated', 'colors.d.ts'),
40
+ prettier.format(
41
+ `export interface DefaultColors { ${JSON.stringify(colorsWithoutDeprecatedColors).slice(
42
+ 1,
43
+ -1
44
+ )}\n${deprecatedColors}\n}`,
45
+ {
46
+ semi: false,
47
+ singleQuote: true,
48
+ printWidth: 100,
49
+ parser: 'typescript',
50
+ }
51
+ )
52
+ )
package/src/cli.js CHANGED
@@ -7,7 +7,7 @@ import path from 'path'
7
7
  import arg from 'arg'
8
8
  import fs from 'fs'
9
9
  import postcssrc from 'postcss-load-config'
10
- import { cosmiconfig } from 'cosmiconfig'
10
+ import { lilconfig } from 'lilconfig'
11
11
  import loadPlugins from 'postcss-load-config/src/plugins' // Little bit scary, looking at private/internal API
12
12
  import tailwind from './processTailwindFeatures'
13
13
  import resolveConfigInternal from '../resolveConfig'
@@ -151,6 +151,10 @@ let commands = {
151
151
  args: {
152
152
  '--full': { type: Boolean, description: 'Initialize a full `tailwind.config.js` file' },
153
153
  '--postcss': { type: Boolean, description: 'Initialize a `postcss.config.js` file' },
154
+ '--types': {
155
+ type: Boolean,
156
+ description: 'Add TypeScript types for the `tailwind.config.js` file',
157
+ },
154
158
  '-f': '--full',
155
159
  '-p': '--postcss',
156
160
  },
@@ -161,6 +165,12 @@ let commands = {
161
165
  '--input': { type: String, description: 'Input file' },
162
166
  '--output': { type: String, description: 'Output file' },
163
167
  '--watch': { type: Boolean, description: 'Watch for changes and rebuild as needed' },
168
+ /*
169
+ '--poll': {
170
+ type: Boolean,
171
+ description: 'Use polling instead of filesystem events when watching',
172
+ },
173
+ */
164
174
  '--content': {
165
175
  type: String,
166
176
  description: 'Content paths to use for removing unused classes',
@@ -187,6 +197,9 @@ let commands = {
187
197
  '-o': '--output',
188
198
  '-m': '--minify',
189
199
  '-w': '--watch',
200
+ /*
201
+ '-p': '--poll',
202
+ */
190
203
  },
191
204
  },
192
205
  }
@@ -204,7 +217,7 @@ if (
204
217
  help({
205
218
  usage: [
206
219
  'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]',
207
- 'tailwindcss init [--full] [--postcss] [options...]',
220
+ 'tailwindcss init [--full] [--postcss] [--types] [options...]',
208
221
  ],
209
222
  commands: Object.keys(commands)
210
223
  .filter((command) => command !== 'build')
@@ -331,6 +344,13 @@ function init() {
331
344
  'utf8'
332
345
  )
333
346
 
347
+ if (args['--types']) {
348
+ let typesHeading = "/** @type {import('tailwindcss/types').Config} */"
349
+ stubFile =
350
+ stubFile.replace(`module.exports = `, `${typesHeading}\nconst config = `) +
351
+ '\nmodule.exports = config'
352
+ }
353
+
334
354
  // Change colors import
335
355
  stubFile = stubFile.replace('../colors', 'tailwindcss/colors')
336
356
 
@@ -367,8 +387,17 @@ async function build() {
367
387
  let input = args['--input']
368
388
  let output = args['--output']
369
389
  let shouldWatch = args['--watch']
390
+ let shouldPoll = false
391
+ /*
392
+ let shouldPoll = args['--poll']
393
+ */
394
+ let shouldCoalesceWriteEvents = shouldPoll || process.platform === 'win32'
370
395
  let includePostCss = args['--postcss']
371
396
 
397
+ // Polling interval in milliseconds
398
+ // Used only when polling or coalescing add/change events on Windows
399
+ let pollInterval = 10
400
+
372
401
  // TODO: Deprecate this in future versions
373
402
  if (!input && args['_'][1]) {
374
403
  console.error('[deprecation] Running tailwindcss without -i, please provide an input file.')
@@ -397,8 +426,8 @@ async function build() {
397
426
  ? await (async () => {
398
427
  let file = path.resolve(customPostCssPath)
399
428
 
400
- // Implementation, see: https://unpkg.com/browse/postcss-load-config@3.0.1/src/index.js
401
- let { config = {} } = await cosmiconfig('postcss').load(file)
429
+ // Implementation, see: https://unpkg.com/browse/postcss-load-config@3.1.0/src/index.js
430
+ let { config = {} } = await lilconfig('postcss').load(file)
402
431
  if (typeof config === 'function') {
403
432
  config = config()
404
433
  } else {
@@ -746,14 +775,15 @@ async function build() {
746
775
  }
747
776
 
748
777
  watcher = chokidar.watch([...contextDependencies, ...extractFileGlobs(config)], {
778
+ usePolling: shouldPoll,
779
+ interval: shouldPoll ? pollInterval : undefined,
749
780
  ignoreInitial: true,
750
- awaitWriteFinish:
751
- process.platform === 'win32'
752
- ? {
753
- stabilityThreshold: 50,
754
- pollInterval: 10,
755
- }
756
- : false,
781
+ awaitWriteFinish: shouldCoalesceWriteEvents
782
+ ? {
783
+ stabilityThreshold: 50,
784
+ pollInterval: pollInterval,
785
+ }
786
+ : false,
757
787
  })
758
788
 
759
789
  let chain = Promise.resolve()
@@ -3,6 +3,7 @@ import * as path from 'path'
3
3
  import postcss from 'postcss'
4
4
  import createUtilityPlugin from './util/createUtilityPlugin'
5
5
  import buildMediaQuery from './util/buildMediaQuery'
6
+ import escapeClassName from './util/escapeClassName'
6
7
  import parseAnimationValue from './util/parseAnimationValue'
7
8
  import flattenColorPalette from './util/flattenColorPalette'
8
9
  import withAlphaVariable, { withAlphaValue } from './util/withAlphaVariable'
@@ -26,6 +27,10 @@ export let variantPlugins = {
26
27
 
27
28
  addVariant('placeholder', '&::placeholder')
28
29
 
30
+ /*
31
+ addVariant('backdrop', '&::backdrop')
32
+ */
33
+
29
34
  addVariant('before', ({ container }) => {
30
35
  container.walkRules((rule) => {
31
36
  let foundContent = false
@@ -70,7 +75,28 @@ export let variantPlugins = {
70
75
  'only-of-type',
71
76
 
72
77
  // State
73
- 'visited',
78
+ [
79
+ 'visited',
80
+ ({ container }) => {
81
+ let toRemove = ['--tw-text-opacity', '--tw-border-opacity', '--tw-bg-opacity']
82
+
83
+ container.walkDecls((decl) => {
84
+ if (toRemove.includes(decl.prop)) {
85
+ decl.remove()
86
+
87
+ return
88
+ }
89
+
90
+ for (const varName of toRemove) {
91
+ if (decl.value.includes(`/ var(${varName})`)) {
92
+ decl.value = decl.value.replace(`/ var(${varName})`, '')
93
+ }
94
+ }
95
+ })
96
+
97
+ return ':visited'
98
+ },
99
+ ],
74
100
  'target',
75
101
  ['open', '[open]'],
76
102
 
@@ -96,19 +122,34 @@ export let variantPlugins = {
96
122
  'focus',
97
123
  'focus-visible',
98
124
  'active',
125
+ /*
126
+ 'enabled',
127
+ */
99
128
  'disabled',
100
129
  ].map((variant) => (Array.isArray(variant) ? variant : [variant, `:${variant}`]))
101
130
 
102
131
  for (let [variantName, state] of pseudoVariants) {
103
- addVariant(variantName, `&${state}`)
132
+ addVariant(variantName, (ctx) => {
133
+ let result = typeof state === 'function' ? state(ctx) : state
134
+
135
+ return `&${result}`
136
+ })
104
137
  }
105
138
 
106
139
  for (let [variantName, state] of pseudoVariants) {
107
- addVariant(`group-${variantName}`, `:merge(.group)${state} &`)
140
+ addVariant(`group-${variantName}`, (ctx) => {
141
+ let result = typeof state === 'function' ? state(ctx) : state
142
+
143
+ return `:merge(.group)${result} &`
144
+ })
108
145
  }
109
146
 
110
147
  for (let [variantName, state] of pseudoVariants) {
111
- addVariant(`peer-${variantName}`, `:merge(.peer)${state} ~ &`)
148
+ addVariant(`peer-${variantName}`, (ctx) => {
149
+ let result = typeof state === 'function' ? state(ctx) : state
150
+
151
+ return `:merge(.peer)${result} ~ &`
152
+ })
112
153
  }
113
154
  },
114
155
 
@@ -138,7 +179,8 @@ export let variantPlugins = {
138
179
  },
139
180
 
140
181
  darkVariants: ({ config, addVariant }) => {
141
- let mode = config('darkMode', 'media')
182
+ let [mode] = [].concat(config('darkMode', 'media'))
183
+
142
184
  if (mode === false) {
143
185
  mode = 'media'
144
186
  log.warn('darkmode-false', [
@@ -149,7 +191,10 @@ export let variantPlugins = {
149
191
  }
150
192
 
151
193
  if (mode === 'class') {
152
- addVariant('dark', '.dark &')
194
+ addVariant('dark', `.dark &`)
195
+ /*
196
+ addVariant('dark', `${className} &`)
197
+ */
153
198
  } else if (mode === 'media') {
154
199
  addVariant('dark', '@media (prefers-color-scheme: dark)')
155
200
  }
@@ -494,6 +539,43 @@ export let corePlugins = {
494
539
  })
495
540
  },
496
541
 
542
+ /*
543
+ borderSpacing: ({ addDefaults, matchUtilities, theme }) => {
544
+ addDefaults('border-spacing', {
545
+ '--tw-border-spacing-x': 0,
546
+ '--tw-border-spacing-y': 0,
547
+ })
548
+
549
+ matchUtilities(
550
+ {
551
+ 'border-spacing': (value) => {
552
+ return {
553
+ '--tw-border-spacing-x': value,
554
+ '--tw-border-spacing-y': value,
555
+ '@defaults border-spacing': {},
556
+ 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
557
+ }
558
+ },
559
+ 'border-spacing-x': (value) => {
560
+ return {
561
+ '--tw-border-spacing-x': value,
562
+ '@defaults border-spacing': {},
563
+ 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
564
+ }
565
+ },
566
+ 'border-spacing-y': (value) => {
567
+ return {
568
+ '--tw-border-spacing-y': value,
569
+ '@defaults border-spacing': {},
570
+ 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
571
+ }
572
+ },
573
+ },
574
+ { values: theme('borderSpacing') }
575
+ )
576
+ },
577
+ */
578
+
497
579
  transformOrigin: createUtilityPlugin('transformOrigin', [['origin', ['transformOrigin']]]),
498
580
  translate: createUtilityPlugin(
499
581
  'translate',
@@ -578,8 +660,8 @@ export let corePlugins = {
578
660
  })
579
661
  },
580
662
 
581
- animation: ({ matchUtilities, theme, prefix }) => {
582
- let prefixName = (name) => prefix(`.${name}`).slice(1)
663
+ animation: ({ matchUtilities, theme, config }) => {
664
+ let prefixName = (name) => `${config('prefix')}${escapeClassName(name)}`
583
665
  let keyframes = Object.fromEntries(
584
666
  Object.entries(theme('keyframes') ?? {}).map(([key, value]) => {
585
667
  return [key, { [`@keyframes ${prefixName(key)}`]: value }]
@@ -1489,6 +1571,10 @@ export let corePlugins = {
1489
1571
  '.text-center': { 'text-align': 'center' },
1490
1572
  '.text-right': { 'text-align': 'right' },
1491
1573
  '.text-justify': { 'text-align': 'justify' },
1574
+ /*
1575
+ '.text-start': { 'text-align': 'start' },
1576
+ '.text-end': { 'text-align': 'end' },
1577
+ */
1492
1578
  })
1493
1579
  },
1494
1580
 
@@ -1892,6 +1978,9 @@ export let corePlugins = {
1892
1978
  ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme }) => {
1893
1979
  let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
1894
1980
  let ringColorDefault = withAlphaValue(
1981
+ /*
1982
+ theme('ringColor')?.DEFAULT,
1983
+ */
1895
1984
  theme('ringColor.DEFAULT'),
1896
1985
  ringOpacityDefault,
1897
1986
  `rgb(147 197 253 / ${ringOpacityDefault})`
@@ -1931,10 +2020,16 @@ export let corePlugins = {
1931
2020
  })
1932
2021
  },
1933
2022
 
1934
- ringColor: ({ matchUtilities, theme }) => {
2023
+ ringColor: ({ matchUtilities, theme, corePlugins }) => {
1935
2024
  matchUtilities(
1936
2025
  {
1937
2026
  ring: (value) => {
2027
+ if (!corePlugins('ringOpacity')) {
2028
+ return {
2029
+ '--tw-ring-color': toColorValue(value),
2030
+ }
2031
+ }
2032
+
1938
2033
  return withAlphaVariable({
1939
2034
  color: value,
1940
2035
  property: '--tw-ring-color',
@@ -1,4 +1,4 @@
1
- import chalk from 'chalk'
1
+ import colors from 'picocolors'
2
2
  import log from './util/log'
3
3
 
4
4
  let defaults = {
@@ -41,7 +41,7 @@ export function issueFlagNotices(config) {
41
41
 
42
42
  if (experimentalFlagsEnabled(config).length > 0) {
43
43
  let changes = experimentalFlagsEnabled(config)
44
- .map((s) => chalk.yellow(s))
44
+ .map((s) => colors.yellow(s))
45
45
  .join(', ')
46
46
 
47
47
  log.warn('experimental-flags-enabled', [
package/src/index.js CHANGED
@@ -13,7 +13,23 @@ module.exports = function tailwindcss(configOrPath) {
13
13
  return root
14
14
  },
15
15
  function (root, result) {
16
- processTailwindFeatures(setupTrackingContext(configOrPath))(root, result)
16
+ let context = setupTrackingContext(configOrPath)
17
+
18
+ /*
19
+ if (root.type === 'document') {
20
+ let roots = root.nodes.filter((node) => node.type === 'root')
21
+
22
+ for (const root of roots) {
23
+ if (root.type === 'root') {
24
+ processTailwindFeatures(context)(root, result)
25
+ }
26
+ }
27
+
28
+ return
29
+ }
30
+ */
31
+
32
+ processTailwindFeatures(context)(root, result)
17
33
  },
18
34
  env.DEBUG &&
19
35
  function (root) {
@@ -0,0 +1,52 @@
1
+ import crypto from 'crypto'
2
+ import * as sharedState from './sharedState'
3
+
4
+ /**
5
+ * Calculate the hash of a string.
6
+ *
7
+ * This doesn't need to be cryptographically secure or
8
+ * anything like that since it's used only to detect
9
+ * when the CSS changes to invalidate the context.
10
+ *
11
+ * This is wrapped in a try/catch because it's really dependent
12
+ * on how Node itself is build and the environment and OpenSSL
13
+ * version / build that is installed on the user's machine.
14
+ *
15
+ * Based on the environment this can just outright fail.
16
+ *
17
+ * See https://github.com/nodejs/node/issues/40455
18
+ *
19
+ * @param {string} str
20
+ */
21
+ function getHash(str) {
22
+ try {
23
+ return crypto.createHash('md5').update(str, 'utf-8').digest('binary')
24
+ } catch (err) {
25
+ return ''
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Determine if the CSS tree is different from the
31
+ * previous version for the given `sourcePath`.
32
+ *
33
+ * @param {string} sourcePath
34
+ * @param {import('postcss').Node} root
35
+ */
36
+ export function hasContentChanged(sourcePath, root) {
37
+ let css = root.toString()
38
+
39
+ // We only care about files with @tailwind directives
40
+ // Other files use an existing context
41
+ if (!css.includes('@tailwind')) {
42
+ return false
43
+ }
44
+
45
+ let existingHash = sharedState.sourceHashMap.get(sourcePath)
46
+ let rootHash = getHash(css)
47
+ let didChange = existingHash !== rootHash
48
+
49
+ sharedState.sourceHashMap.set(sourcePath, rootHash)
50
+
51
+ return didChange
52
+ }
@@ -5,7 +5,7 @@ let comparisonMap = {
5
5
  let types = new Set(Object.keys(comparisonMap))
6
6
 
7
7
  export default function collapseAdjacentRules() {
8
- return (root) => {
8
+ function collapseRulesIn(root) {
9
9
  let currentRule = null
10
10
  root.each((node) => {
11
11
  if (!types.has(node.type)) {
@@ -35,5 +35,20 @@ export default function collapseAdjacentRules() {
35
35
  currentRule = node
36
36
  }
37
37
  })
38
+
39
+ // After we've collapsed adjacent rules & at-rules, we need to collapse
40
+ // adjacent rules & at-rules that are children of at-rules.
41
+ // We do not care about nesting rules because Tailwind CSS
42
+ // explicitly does not handle rule nesting on its own as
43
+ // the user is expected to use a nesting plugin
44
+ root.each((node) => {
45
+ if (node.type === 'atrule') {
46
+ collapseRulesIn(node)
47
+ }
48
+ })
49
+ }
50
+
51
+ return (root) => {
52
+ collapseRulesIn(root)
38
53
  }
39
54
  }
@@ -2,14 +2,16 @@ const PATTERNS = [
2
2
  /(?:\['([^'\s]+[^<>"'`\s:\\])')/.source, // ['text-lg' -> text-lg
3
3
  /(?:\["([^"\s]+[^<>"'`\s:\\])")/.source, // ["text-lg" -> text-lg
4
4
  /(?:\[`([^`\s]+[^<>"'`\s:\\])`)/.source, // [`text-lg` -> text-lg
5
- /([^<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source, // font-['some_font',sans-serif]
6
- /([^<>"'`\s]*\[\w*"[^'`\s]*"?\])/.source, // font-["some_font",sans-serif]
5
+ /([^${(<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source, // font-['some_font',sans-serif]
6
+ /([^${(<>"'`\s]*\[\w*"[^'`\s]*"?\])/.source, // font-["some_font",sans-serif]
7
7
  /([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source, // bg-[url('...')]
8
8
  /([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source, // bg-[url("...")]
9
9
  /([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source, // bg-[url('...'),url('...')]
10
10
  /([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source, // bg-[url("..."),url("...")]
11
- /([^<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
12
- /([^<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
11
+ /([^<>"'`\s]*\[[^<>"'`\s]*\('[^"`\s]*'\)+\])/.source, // h-[calc(100%-theme('spacing.1'))]
12
+ /([^<>"'`\s]*\[[^<>"'`\s]*\("[^'`\s]*"\)+\])/.source, // h-[calc(100%-theme("spacing.1"))]
13
+ /([^${(<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
14
+ /([^${(<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
13
15
  /([^<>"'`\s]*\[[^<>"'`\s]*:[^\]\s]*\])/.source, // `[attr:value]`
14
16
  /([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source, // `[content:'hello']` but not `[content:"hello"]`
15
17
  /([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source, // `[content:"hello"]` but not `[content:'hello']`