tailwindcss 3.0.23 → 3.1.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.
Files changed (119) hide show
  1. package/CHANGELOG.md +92 -2
  2. package/colors.d.ts +3 -0
  3. package/defaultConfig.d.ts +3 -0
  4. package/defaultTheme.d.ts +3 -0
  5. package/lib/cli-peer-dependencies.js +10 -5
  6. package/lib/cli.js +266 -203
  7. package/lib/constants.js +8 -8
  8. package/lib/corePluginList.js +1 -0
  9. package/lib/corePlugins.js +1640 -1562
  10. package/lib/css/preflight.css +1 -8
  11. package/lib/featureFlags.js +14 -12
  12. package/lib/index.js +16 -6
  13. package/lib/lib/cacheInvalidation.js +87 -0
  14. package/lib/lib/collapseAdjacentRules.js +30 -15
  15. package/lib/lib/collapseDuplicateDeclarations.js +1 -1
  16. package/lib/lib/defaultExtractor.js +191 -32
  17. package/lib/lib/detectNesting.js +9 -9
  18. package/lib/lib/evaluateTailwindFunctions.js +37 -28
  19. package/lib/lib/expandApplyAtRules.js +379 -189
  20. package/lib/lib/expandTailwindAtRules.js +168 -144
  21. package/lib/lib/generateRules.js +177 -95
  22. package/lib/lib/getModuleDependencies.js +14 -14
  23. package/lib/lib/normalizeTailwindDirectives.js +35 -35
  24. package/lib/lib/partitionApplyAtRules.js +7 -7
  25. package/lib/lib/regex.js +52 -0
  26. package/lib/lib/resolveDefaultsAtRules.js +96 -81
  27. package/lib/lib/setupContextUtils.js +202 -159
  28. package/lib/lib/setupTrackingContext.js +61 -63
  29. package/lib/lib/sharedState.js +10 -9
  30. package/lib/lib/substituteScreenAtRules.js +3 -4
  31. package/lib/postcss-plugins/nesting/README.md +2 -2
  32. package/lib/postcss-plugins/nesting/index.js +1 -1
  33. package/lib/postcss-plugins/nesting/plugin.js +40 -9
  34. package/lib/processTailwindFeatures.js +7 -7
  35. package/lib/public/colors.js +241 -241
  36. package/lib/public/resolve-config.js +5 -5
  37. package/lib/util/buildMediaQuery.js +2 -3
  38. package/lib/util/cloneDeep.js +3 -5
  39. package/lib/util/cloneNodes.js +12 -1
  40. package/lib/util/color.js +42 -51
  41. package/lib/util/createPlugin.js +1 -2
  42. package/lib/util/createUtilityPlugin.js +6 -7
  43. package/lib/util/dataTypes.js +85 -81
  44. package/lib/util/escapeClassName.js +5 -5
  45. package/lib/util/escapeCommas.js +1 -1
  46. package/lib/util/flattenColorPalette.js +4 -7
  47. package/lib/util/formatVariantSelector.js +82 -75
  48. package/lib/util/getAllConfigs.js +15 -10
  49. package/lib/util/hashConfig.js +5 -5
  50. package/lib/util/isKeyframeRule.js +1 -1
  51. package/lib/util/isPlainObject.js +1 -1
  52. package/lib/util/isValidArbitraryValue.js +26 -27
  53. package/lib/util/log.js +9 -10
  54. package/lib/util/nameClass.js +7 -7
  55. package/lib/util/negateValue.js +4 -5
  56. package/lib/util/normalizeConfig.js +68 -58
  57. package/lib/util/normalizeScreens.js +5 -6
  58. package/lib/util/parseAnimationValue.js +56 -57
  59. package/lib/util/parseBoxShadowValue.js +19 -20
  60. package/lib/util/parseDependency.js +32 -32
  61. package/lib/util/parseObjectStyles.js +6 -6
  62. package/lib/util/pluginUtils.js +20 -12
  63. package/lib/util/prefixSelector.js +1 -1
  64. package/lib/util/resolveConfig.js +81 -58
  65. package/lib/util/resolveConfigPath.js +16 -16
  66. package/lib/util/responsive.js +6 -6
  67. package/lib/util/splitAtTopLevelOnly.js +90 -0
  68. package/lib/util/toColorValue.js +1 -1
  69. package/lib/util/toPath.js +2 -2
  70. package/lib/util/transformThemeValue.js +30 -28
  71. package/lib/util/validateConfig.js +21 -0
  72. package/lib/util/withAlphaVariable.js +23 -23
  73. package/package.json +33 -27
  74. package/peers/index.js +7702 -5822
  75. package/plugin.d.ts +11 -0
  76. package/scripts/generate-types.js +52 -0
  77. package/src/cli-peer-dependencies.js +7 -1
  78. package/src/cli.js +118 -24
  79. package/src/corePluginList.js +1 -1
  80. package/src/corePlugins.js +109 -30
  81. package/src/css/preflight.css +1 -8
  82. package/src/featureFlags.js +4 -4
  83. package/src/index.js +15 -1
  84. package/src/lib/cacheInvalidation.js +52 -0
  85. package/src/lib/collapseAdjacentRules.js +21 -2
  86. package/src/lib/defaultExtractor.js +177 -35
  87. package/src/lib/evaluateTailwindFunctions.js +20 -4
  88. package/src/lib/expandApplyAtRules.js +418 -186
  89. package/src/lib/expandTailwindAtRules.js +29 -9
  90. package/src/lib/generateRules.js +137 -51
  91. package/src/lib/regex.js +74 -0
  92. package/src/lib/resolveDefaultsAtRules.js +53 -32
  93. package/src/lib/setupContextUtils.js +128 -65
  94. package/src/lib/setupTrackingContext.js +7 -3
  95. package/src/lib/sharedState.js +1 -0
  96. package/src/postcss-plugins/nesting/README.md +2 -2
  97. package/src/postcss-plugins/nesting/plugin.js +36 -0
  98. package/src/util/cloneNodes.js +14 -1
  99. package/src/util/color.js +25 -21
  100. package/src/util/dataTypes.js +14 -6
  101. package/src/util/formatVariantSelector.js +79 -62
  102. package/src/util/getAllConfigs.js +7 -0
  103. package/src/util/log.js +8 -8
  104. package/src/util/normalizeConfig.js +0 -8
  105. package/src/util/parseBoxShadowValue.js +3 -2
  106. package/src/util/pluginUtils.js +13 -1
  107. package/src/util/resolveConfig.js +66 -22
  108. package/src/util/splitAtTopLevelOnly.js +71 -0
  109. package/src/util/toPath.js +1 -1
  110. package/src/util/transformThemeValue.js +4 -2
  111. package/src/util/validateConfig.js +13 -0
  112. package/src/util/withAlphaVariable.js +1 -1
  113. package/stubs/defaultConfig.stub.js +5 -1
  114. package/stubs/simpleConfig.stub.js +1 -0
  115. package/types/config.d.ts +325 -0
  116. package/types/generated/.gitkeep +0 -0
  117. package/types/generated/colors.d.ts +276 -0
  118. package/types/generated/corePluginList.d.ts +1 -0
  119. package/types/index.d.ts +7 -0
@@ -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'
@@ -13,6 +14,7 @@ import { version as tailwindVersion } from '../package.json'
13
14
  import log from './util/log'
14
15
  import { normalizeScreens } from './util/normalizeScreens'
15
16
  import { formatBoxShadowValue, parseBoxShadowValue } from './util/parseBoxShadowValue'
17
+ import { flagEnabled } from './featureFlags'
16
18
 
17
19
  export let variantPlugins = {
18
20
  pseudoElementVariants: ({ addVariant }) => {
@@ -26,6 +28,8 @@ export let variantPlugins = {
26
28
 
27
29
  addVariant('placeholder', '&::placeholder')
28
30
 
31
+ addVariant('backdrop', '&::backdrop')
32
+
29
33
  addVariant('before', ({ container }) => {
30
34
  container.walkRules((rule) => {
31
35
  let foundContent = false
@@ -57,14 +61,14 @@ export let variantPlugins = {
57
61
  })
58
62
  },
59
63
 
60
- pseudoClassVariants: ({ addVariant }) => {
64
+ pseudoClassVariants: ({ addVariant, config }) => {
61
65
  let pseudoVariants = [
62
66
  // Positional
63
- ['first', ':first-child'],
64
- ['last', ':last-child'],
65
- ['only', ':only-child'],
66
- ['odd', ':nth-child(odd)'],
67
- ['even', ':nth-child(even)'],
67
+ ['first', '&:first-child'],
68
+ ['last', '&:last-child'],
69
+ ['only', '&:only-child'],
70
+ ['odd', '&:nth-child(odd)'],
71
+ ['even', '&:nth-child(even)'],
68
72
  'first-of-type',
69
73
  'last-of-type',
70
74
  'only-of-type',
@@ -89,11 +93,11 @@ export let variantPlugins = {
89
93
  }
90
94
  })
91
95
 
92
- return ':visited'
96
+ return '&:visited'
93
97
  },
94
98
  ],
95
99
  'target',
96
- ['open', '[open]'],
100
+ ['open', '&[open]'],
97
101
 
98
102
  // Forms
99
103
  'default',
@@ -101,6 +105,7 @@ export let variantPlugins = {
101
105
  'indeterminate',
102
106
  'placeholder-shown',
103
107
  'autofill',
108
+ 'optional',
104
109
  'required',
105
110
  'valid',
106
111
  'invalid',
@@ -113,18 +118,24 @@ export let variantPlugins = {
113
118
 
114
119
  // Interactive
115
120
  'focus-within',
116
- 'hover',
121
+ [
122
+ 'hover',
123
+ !flagEnabled(config(), 'hoverOnlyWhenSupported')
124
+ ? '&:hover'
125
+ : '@media (hover: hover) and (pointer: fine) { &:hover }',
126
+ ],
117
127
  'focus',
118
128
  'focus-visible',
119
129
  'active',
130
+ 'enabled',
120
131
  'disabled',
121
- ].map((variant) => (Array.isArray(variant) ? variant : [variant, `:${variant}`]))
132
+ ].map((variant) => (Array.isArray(variant) ? variant : [variant, `&:${variant}`]))
122
133
 
123
134
  for (let [variantName, state] of pseudoVariants) {
124
135
  addVariant(variantName, (ctx) => {
125
136
  let result = typeof state === 'function' ? state(ctx) : state
126
137
 
127
- return `&${result}`
138
+ return result
128
139
  })
129
140
  }
130
141
 
@@ -132,7 +143,7 @@ export let variantPlugins = {
132
143
  addVariant(`group-${variantName}`, (ctx) => {
133
144
  let result = typeof state === 'function' ? state(ctx) : state
134
145
 
135
- return `:merge(.group)${result} &`
146
+ return result.replace(/&(\S+)/, ':merge(.group)$1 &')
136
147
  })
137
148
  }
138
149
 
@@ -140,7 +151,7 @@ export let variantPlugins = {
140
151
  addVariant(`peer-${variantName}`, (ctx) => {
141
152
  let result = typeof state === 'function' ? state(ctx) : state
142
153
 
143
- return `:merge(.peer)${result} ~ &`
154
+ return result.replace(/&(\S+)/, ':merge(.peer)$1 ~ &')
144
155
  })
145
156
  }
146
157
  },
@@ -171,7 +182,8 @@ export let variantPlugins = {
171
182
  },
172
183
 
173
184
  darkVariants: ({ config, addVariant }) => {
174
- let mode = config('darkMode', 'media')
185
+ let [mode, className = '.dark'] = [].concat(config('darkMode', 'media'))
186
+
175
187
  if (mode === false) {
176
188
  mode = 'media'
177
189
  log.warn('darkmode-false', [
@@ -182,7 +194,7 @@ export let variantPlugins = {
182
194
  }
183
195
 
184
196
  if (mode === 'class') {
185
- addVariant('dark', '.dark &')
197
+ addVariant('dark', `${className} &`)
186
198
  } else if (mode === 'media') {
187
199
  addVariant('dark', '@media (prefers-color-scheme: dark)')
188
200
  }
@@ -204,6 +216,11 @@ export let variantPlugins = {
204
216
  addVariant('portrait', '@media (orientation: portrait)')
205
217
  addVariant('landscape', '@media (orientation: landscape)')
206
218
  },
219
+
220
+ prefersContrastVariants: ({ addVariant }) => {
221
+ addVariant('contrast-more', '@media (prefers-contrast: more)')
222
+ addVariant('contrast-less', '@media (prefers-contrast: less)')
223
+ },
207
224
  }
208
225
 
209
226
  let cssTransformValue = [
@@ -527,6 +544,41 @@ export let corePlugins = {
527
544
  })
528
545
  },
529
546
 
547
+ borderSpacing: ({ addDefaults, matchUtilities, theme }) => {
548
+ addDefaults('border-spacing', {
549
+ '--tw-border-spacing-x': 0,
550
+ '--tw-border-spacing-y': 0,
551
+ })
552
+
553
+ matchUtilities(
554
+ {
555
+ 'border-spacing': (value) => {
556
+ return {
557
+ '--tw-border-spacing-x': value,
558
+ '--tw-border-spacing-y': value,
559
+ '@defaults border-spacing': {},
560
+ 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
561
+ }
562
+ },
563
+ 'border-spacing-x': (value) => {
564
+ return {
565
+ '--tw-border-spacing-x': value,
566
+ '@defaults border-spacing': {},
567
+ 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
568
+ }
569
+ },
570
+ 'border-spacing-y': (value) => {
571
+ return {
572
+ '--tw-border-spacing-y': value,
573
+ '@defaults border-spacing': {},
574
+ 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
575
+ }
576
+ },
577
+ },
578
+ { values: theme('borderSpacing') }
579
+ )
580
+ },
581
+
530
582
  transformOrigin: createUtilityPlugin('transformOrigin', [['origin', ['transformOrigin']]]),
531
583
  translate: createUtilityPlugin(
532
584
  'translate',
@@ -611,8 +663,8 @@ export let corePlugins = {
611
663
  })
612
664
  },
613
665
 
614
- animation: ({ matchUtilities, theme, prefix }) => {
615
- let prefixName = (name) => prefix(`.${name}`).slice(1)
666
+ animation: ({ matchUtilities, theme, config }) => {
667
+ let prefixName = (name) => `${config('prefix')}${escapeClassName(name)}`
616
668
  let keyframes = Object.fromEntries(
617
669
  Object.entries(theme('keyframes') ?? {}).map(([key, value]) => {
618
670
  return [key, { [`@keyframes ${prefixName(key)}`]: value }]
@@ -844,6 +896,7 @@ export let corePlugins = {
844
896
  addUtilities({
845
897
  '.grid-flow-row': { gridAutoFlow: 'row' },
846
898
  '.grid-flow-col': { gridAutoFlow: 'column' },
899
+ '.grid-flow-dense': { gridAutoFlow: 'dense' },
847
900
  '.grid-flow-row-dense': { gridAutoFlow: 'row dense' },
848
901
  '.grid-flow-col-dense': { gridAutoFlow: 'column dense' },
849
902
  })
@@ -1384,7 +1437,8 @@ export let corePlugins = {
1384
1437
 
1385
1438
  return {
1386
1439
  '--tw-gradient-from': toColorValue(value, 'from'),
1387
- '--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to, ${transparentToValue})`,
1440
+ '--tw-gradient-to': transparentToValue,
1441
+ '--tw-gradient-stops': `var(--tw-gradient-from), var(--tw-gradient-to)`,
1388
1442
  }
1389
1443
  },
1390
1444
  },
@@ -1396,10 +1450,11 @@ export let corePlugins = {
1396
1450
  let transparentToValue = transparentTo(value)
1397
1451
 
1398
1452
  return {
1453
+ '--tw-gradient-to': transparentToValue,
1399
1454
  '--tw-gradient-stops': `var(--tw-gradient-from), ${toColorValue(
1400
1455
  value,
1401
1456
  'via'
1402
- )}, var(--tw-gradient-to, ${transparentToValue})`,
1457
+ )}, var(--tw-gradient-to)`,
1403
1458
  }
1404
1459
  },
1405
1460
  },
@@ -1522,6 +1577,8 @@ export let corePlugins = {
1522
1577
  '.text-center': { 'text-align': 'center' },
1523
1578
  '.text-right': { 'text-align': 'right' },
1524
1579
  '.text-justify': { 'text-align': 'justify' },
1580
+ '.text-start': { 'text-align': 'start' },
1581
+ '.text-end': { 'text-align': 'end' },
1525
1582
  })
1526
1583
  },
1527
1584
 
@@ -1828,6 +1885,7 @@ export let corePlugins = {
1828
1885
  '.mix-blend-saturation': { 'mix-blend-mode': 'saturation' },
1829
1886
  '.mix-blend-color': { 'mix-blend-mode': 'color' },
1830
1887
  '.mix-blend-luminosity': { 'mix-blend-mode': 'luminosity' },
1888
+ '.mix-blend-plus-lighter': { 'mix-blend-mode': 'plus-lighter' },
1831
1889
  })
1832
1890
  },
1833
1891
 
@@ -1922,13 +1980,24 @@ export let corePlugins = {
1922
1980
  )
1923
1981
  },
1924
1982
 
1925
- ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme }) => {
1926
- let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
1927
- let ringColorDefault = withAlphaValue(
1928
- theme('ringColor.DEFAULT'),
1929
- ringOpacityDefault,
1930
- `rgb(147 197 253 / ${ringOpacityDefault})`
1931
- )
1983
+ ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme, config }) => {
1984
+ let ringColorDefault = (() => {
1985
+ if (flagEnabled(config(), 'respectDefaultRingColorOpacity')) {
1986
+ return theme('ringColor.DEFAULT')
1987
+ }
1988
+
1989
+ let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
1990
+
1991
+ if (!theme('ringColor')?.DEFAULT) {
1992
+ return `rgb(147 197 253 / ${ringOpacityDefault})`
1993
+ }
1994
+
1995
+ return withAlphaValue(
1996
+ theme('ringColor')?.DEFAULT,
1997
+ ringOpacityDefault,
1998
+ `rgb(147 197 253 / ${ringOpacityDefault})`
1999
+ )
2000
+ })()
1932
2001
 
1933
2002
  addDefaults('ring-width', {
1934
2003
  '--tw-ring-inset': ' ',
@@ -1964,10 +2033,16 @@ export let corePlugins = {
1964
2033
  })
1965
2034
  },
1966
2035
 
1967
- ringColor: ({ matchUtilities, theme }) => {
2036
+ ringColor: ({ matchUtilities, theme, corePlugins }) => {
1968
2037
  matchUtilities(
1969
2038
  {
1970
2039
  ring: (value) => {
2040
+ if (!corePlugins('ringOpacity')) {
2041
+ return {
2042
+ '--tw-ring-color': toColorValue(value),
2043
+ }
2044
+ }
2045
+
1971
2046
  return withAlphaVariable({
1972
2047
  color: value,
1973
2048
  property: '--tw-ring-color',
@@ -1986,9 +2061,13 @@ export let corePlugins = {
1986
2061
  )
1987
2062
  },
1988
2063
 
1989
- ringOpacity: createUtilityPlugin('ringOpacity', [['ring-opacity', ['--tw-ring-opacity']]], {
1990
- filterDefault: true,
1991
- }),
2064
+ ringOpacity: (helpers) => {
2065
+ let { config } = helpers
2066
+
2067
+ return createUtilityPlugin('ringOpacity', [['ring-opacity', ['--tw-ring-opacity']]], {
2068
+ filterDefault: !flagEnabled(config(), 'respectDefaultRingColorOpacity'),
2069
+ })(helpers)
2070
+ },
1992
2071
  ringOffsetWidth: createUtilityPlugin(
1993
2072
  'ringOffsetWidth',
1994
2073
  [['ring-offset', ['--tw-ring-offset-width']]],
@@ -160,6 +160,7 @@ select,
160
160
  textarea {
161
161
  font-family: inherit; /* 1 */
162
162
  font-size: 100%; /* 1 */
163
+ font-weight: inherit; /* 1 */
163
164
  line-height: inherit; /* 1 */
164
165
  color: inherit; /* 1 */
165
166
  margin: 0; /* 2 */
@@ -357,11 +358,3 @@ video {
357
358
  max-width: 100%;
358
359
  height: auto;
359
360
  }
360
-
361
- /*
362
- Ensure the default browser behavior of the `hidden` attribute.
363
- */
364
-
365
- [hidden] {
366
- display: none;
367
- }
@@ -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 = {
@@ -6,8 +6,8 @@ let defaults = {
6
6
  }
7
7
 
8
8
  let featureFlags = {
9
- future: [],
10
- experimental: ['optimizeUniversalDefaults'],
9
+ future: ['hoverOnlyWhenSupported', 'respectDefaultRingColorOpacity'],
10
+ experimental: ['optimizeUniversalDefaults', 'matchVariant' /* , 'variantGrouping' */],
11
11
  }
12
12
 
13
13
  export function flagEnabled(config, flag) {
@@ -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,21 @@ 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
+ if (root.type === 'document') {
19
+ let roots = root.nodes.filter((node) => node.type === 'root')
20
+
21
+ for (const root of roots) {
22
+ if (root.type === 'root') {
23
+ processTailwindFeatures(context)(root, result)
24
+ }
25
+ }
26
+
27
+ return
28
+ }
29
+
30
+ processTailwindFeatures(context)(root, result)
17
31
  },
18
32
  env.DEBUG &&
19
33
  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)) {
@@ -29,11 +29,30 @@ export default function collapseAdjacentRules() {
29
29
  (currentRule[property] ?? '').replace(/\s+/g, ' ')
30
30
  )
31
31
  ) {
32
- currentRule.append(node.nodes)
32
+ // An AtRule may not have children (for example if we encounter duplicate @import url(…) rules)
33
+ if (node.nodes) {
34
+ currentRule.append(node.nodes)
35
+ }
36
+
33
37
  node.remove()
34
38
  } else {
35
39
  currentRule = node
36
40
  }
37
41
  })
42
+
43
+ // After we've collapsed adjacent rules & at-rules, we need to collapse
44
+ // adjacent rules & at-rules that are children of at-rules.
45
+ // We do not care about nesting rules because Tailwind CSS
46
+ // explicitly does not handle rule nesting on its own as
47
+ // the user is expected to use a nesting plugin
48
+ root.each((node) => {
49
+ if (node.type === 'atrule') {
50
+ collapseRulesIn(node)
51
+ }
52
+ })
53
+ }
54
+
55
+ return (root) => {
56
+ collapseRulesIn(root)
38
57
  }
39
58
  }