tailwindcss 0.0.0-insiders.f4635e0 → 0.0.0-insiders.f4a2ccd

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 (238) hide show
  1. package/LICENSE +1 -2
  2. package/README.md +15 -7
  3. package/colors.d.ts +3 -0
  4. package/colors.js +2 -304
  5. package/defaultConfig.d.ts +3 -0
  6. package/defaultConfig.js +2 -4
  7. package/defaultTheme.d.ts +4 -0
  8. package/defaultTheme.js +2 -4
  9. package/lib/cli/build/deps.js +54 -0
  10. package/lib/cli/build/index.js +52 -0
  11. package/lib/cli/build/plugin.js +376 -0
  12. package/lib/cli/build/utils.js +78 -0
  13. package/lib/cli/build/watching.js +180 -0
  14. package/lib/cli/help/index.js +71 -0
  15. package/lib/cli/index.js +230 -0
  16. package/lib/cli/init/index.js +61 -0
  17. package/lib/cli-peer-dependencies.js +22 -14
  18. package/lib/cli.js +4 -762
  19. package/lib/corePluginList.js +182 -5
  20. package/lib/corePlugins.js +4109 -2952
  21. package/lib/css/preflight.css +24 -9
  22. package/lib/featureFlags.js +68 -50
  23. package/lib/index.js +5 -30
  24. package/lib/lib/cacheInvalidation.js +90 -0
  25. package/lib/lib/collapseAdjacentRules.js +52 -36
  26. package/lib/lib/collapseDuplicateDeclarations.js +83 -0
  27. package/lib/lib/content.js +177 -0
  28. package/lib/lib/defaultExtractor.js +241 -0
  29. package/lib/lib/detectNesting.js +39 -17
  30. package/lib/lib/evaluateTailwindFunctions.js +203 -161
  31. package/lib/lib/expandApplyAtRules.js +503 -221
  32. package/lib/lib/expandTailwindAtRules.js +255 -243
  33. package/lib/lib/findAtConfigPath.js +44 -0
  34. package/lib/lib/generateRules.js +831 -317
  35. package/lib/lib/getModuleDependencies.js +93 -49
  36. package/lib/lib/load-config.js +36 -0
  37. package/lib/lib/normalizeTailwindDirectives.js +79 -60
  38. package/lib/lib/offsets.js +304 -0
  39. package/lib/lib/partitionApplyAtRules.js +56 -0
  40. package/lib/lib/regex.js +60 -0
  41. package/lib/lib/remap-bitfield.js +87 -0
  42. package/lib/lib/resolveDefaultsAtRules.js +150 -94
  43. package/lib/lib/setupContextUtils.js +1197 -685
  44. package/lib/lib/setupTrackingContext.js +150 -177
  45. package/lib/lib/sharedState.js +70 -21
  46. package/lib/lib/substituteScreenAtRules.js +26 -28
  47. package/lib/oxide/cli/build/deps.js +81 -0
  48. package/lib/oxide/cli/build/index.js +51 -0
  49. package/lib/oxide/cli/build/plugin.js +373 -0
  50. package/lib/oxide/cli/build/utils.js +77 -0
  51. package/lib/oxide/cli/build/watching.js +177 -0
  52. package/lib/oxide/cli/help/index.js +70 -0
  53. package/lib/oxide/cli/index.js +214 -0
  54. package/lib/oxide/cli/init/index.js +50 -0
  55. package/lib/oxide/cli.js +5 -0
  56. package/lib/oxide/postcss-plugin.js +2 -0
  57. package/lib/plugin.js +98 -0
  58. package/{nesting → lib/postcss-plugins/nesting}/README.md +2 -2
  59. package/lib/postcss-plugins/nesting/index.js +19 -0
  60. package/lib/postcss-plugins/nesting/plugin.js +87 -0
  61. package/lib/processTailwindFeatures.js +58 -56
  62. package/lib/public/colors.js +353 -0
  63. package/lib/public/create-plugin.js +15 -0
  64. package/lib/public/default-config.js +16 -0
  65. package/lib/public/default-theme.js +16 -0
  66. package/lib/public/load-config.js +10 -0
  67. package/lib/public/resolve-config.js +22 -0
  68. package/lib/util/applyImportantSelector.js +22 -0
  69. package/lib/util/bigSign.js +7 -6
  70. package/lib/util/buildMediaQuery.js +21 -32
  71. package/lib/util/cloneDeep.js +16 -14
  72. package/lib/util/cloneNodes.js +29 -15
  73. package/lib/util/color.js +104 -66
  74. package/lib/util/configurePlugins.js +17 -15
  75. package/lib/util/createPlugin.js +23 -26
  76. package/lib/util/createUtilityPlugin.js +46 -46
  77. package/lib/util/dataTypes.js +266 -0
  78. package/lib/util/defaults.js +20 -15
  79. package/lib/util/escapeClassName.js +18 -17
  80. package/lib/util/escapeCommas.js +7 -6
  81. package/lib/util/flattenColorPalette.js +13 -12
  82. package/lib/util/formatVariantSelector.js +341 -0
  83. package/lib/util/getAllConfigs.js +44 -18
  84. package/lib/util/hashConfig.js +15 -12
  85. package/lib/util/isKeyframeRule.js +7 -6
  86. package/lib/util/isPlainObject.js +11 -11
  87. package/lib/util/isSyntacticallyValidPropertyValue.js +72 -0
  88. package/lib/util/log.js +52 -33
  89. package/lib/util/nameClass.js +35 -29
  90. package/lib/util/negateValue.js +31 -17
  91. package/lib/util/normalizeConfig.js +294 -0
  92. package/lib/util/normalizeScreens.js +170 -0
  93. package/lib/util/parseAnimationValue.js +85 -54
  94. package/lib/util/parseBoxShadowValue.js +84 -0
  95. package/lib/util/parseDependency.js +41 -70
  96. package/lib/util/parseGlob.js +34 -0
  97. package/lib/util/parseObjectStyles.js +30 -24
  98. package/lib/util/pluginUtils.js +234 -288
  99. package/lib/util/prefixSelector.js +33 -19
  100. package/lib/util/removeAlphaVariables.js +29 -0
  101. package/lib/util/resolveConfig.js +221 -256
  102. package/lib/util/resolveConfigPath.js +55 -48
  103. package/lib/util/responsive.js +18 -14
  104. package/lib/util/splitAtTopLevelOnly.js +49 -0
  105. package/lib/util/tap.js +8 -7
  106. package/lib/util/toColorValue.js +7 -6
  107. package/lib/util/toPath.js +27 -8
  108. package/lib/util/transformThemeValue.js +67 -28
  109. package/lib/util/validateConfig.js +24 -0
  110. package/lib/util/validateFormalSyntax.js +24 -0
  111. package/lib/util/withAlphaVariable.js +67 -57
  112. package/loadConfig.d.ts +4 -0
  113. package/loadConfig.js +2 -0
  114. package/nesting/index.js +2 -12
  115. package/package.json +69 -66
  116. package/peers/index.js +76328 -84169
  117. package/plugin.d.ts +11 -0
  118. package/plugin.js +1 -2
  119. package/resolveConfig.d.ts +12 -0
  120. package/resolveConfig.js +2 -7
  121. package/scripts/create-plugin-list.js +2 -2
  122. package/scripts/generate-types.js +105 -0
  123. package/scripts/release-channel.js +18 -0
  124. package/scripts/release-notes.js +21 -0
  125. package/scripts/swap-engines.js +40 -0
  126. package/scripts/type-utils.js +27 -0
  127. package/src/cli/build/deps.js +56 -0
  128. package/src/cli/build/index.js +49 -0
  129. package/src/cli/build/plugin.js +444 -0
  130. package/src/cli/build/utils.js +76 -0
  131. package/src/cli/build/watching.js +229 -0
  132. package/src/cli/help/index.js +70 -0
  133. package/src/cli/index.js +216 -0
  134. package/src/cli/init/index.js +79 -0
  135. package/src/cli-peer-dependencies.js +7 -1
  136. package/src/cli.js +4 -756
  137. package/src/corePluginList.js +1 -1
  138. package/src/corePlugins.js +2526 -1956
  139. package/src/css/preflight.css +24 -9
  140. package/src/featureFlags.js +33 -10
  141. package/src/index.js +4 -33
  142. package/src/lib/cacheInvalidation.js +52 -0
  143. package/src/lib/collapseAdjacentRules.js +21 -2
  144. package/src/lib/collapseDuplicateDeclarations.js +93 -0
  145. package/src/lib/content.js +208 -0
  146. package/src/lib/defaultExtractor.js +217 -0
  147. package/src/lib/detectNesting.js +30 -3
  148. package/src/lib/evaluateTailwindFunctions.js +84 -10
  149. package/src/lib/expandApplyAtRules.js +509 -153
  150. package/src/lib/expandTailwindAtRules.js +125 -104
  151. package/src/lib/findAtConfigPath.js +48 -0
  152. package/src/lib/generateRules.js +678 -70
  153. package/src/lib/getModuleDependencies.js +70 -30
  154. package/src/lib/load-config.ts +27 -0
  155. package/src/lib/normalizeTailwindDirectives.js +10 -3
  156. package/src/lib/offsets.js +373 -0
  157. package/src/lib/partitionApplyAtRules.js +52 -0
  158. package/src/lib/regex.js +74 -0
  159. package/src/lib/remap-bitfield.js +82 -0
  160. package/src/lib/resolveDefaultsAtRules.js +105 -47
  161. package/src/lib/setupContextUtils.js +848 -247
  162. package/src/lib/setupTrackingContext.js +53 -64
  163. package/src/lib/sharedState.js +60 -6
  164. package/src/lib/substituteScreenAtRules.js +6 -3
  165. package/src/oxide/cli/build/deps.ts +91 -0
  166. package/src/oxide/cli/build/index.ts +47 -0
  167. package/src/oxide/cli/build/plugin.ts +442 -0
  168. package/src/oxide/cli/build/utils.ts +74 -0
  169. package/src/oxide/cli/build/watching.ts +225 -0
  170. package/src/oxide/cli/help/index.ts +69 -0
  171. package/src/oxide/cli/index.ts +204 -0
  172. package/src/oxide/cli/init/index.ts +59 -0
  173. package/src/oxide/cli.ts +1 -0
  174. package/src/oxide/postcss-plugin.ts +1 -0
  175. package/src/plugin.js +107 -0
  176. package/src/postcss-plugins/nesting/README.md +42 -0
  177. package/src/postcss-plugins/nesting/index.js +13 -0
  178. package/src/postcss-plugins/nesting/plugin.js +80 -0
  179. package/src/processTailwindFeatures.js +18 -3
  180. package/src/public/colors.js +322 -0
  181. package/src/public/create-plugin.js +2 -0
  182. package/src/public/default-config.js +4 -0
  183. package/src/public/default-theme.js +4 -0
  184. package/src/public/load-config.js +2 -0
  185. package/src/public/resolve-config.js +7 -0
  186. package/src/util/applyImportantSelector.js +19 -0
  187. package/src/util/buildMediaQuery.js +14 -16
  188. package/src/util/cloneNodes.js +19 -2
  189. package/src/util/color.js +43 -11
  190. package/src/util/createUtilityPlugin.js +2 -11
  191. package/src/util/dataTypes.js +281 -0
  192. package/src/util/defaults.js +6 -0
  193. package/src/util/formatVariantSelector.js +412 -0
  194. package/src/util/getAllConfigs.js +21 -2
  195. package/src/util/isSyntacticallyValidPropertyValue.js +61 -0
  196. package/src/util/log.js +23 -22
  197. package/src/util/nameClass.js +6 -2
  198. package/src/util/negateValue.js +15 -5
  199. package/src/util/normalizeConfig.js +318 -0
  200. package/src/util/normalizeScreens.js +140 -0
  201. package/src/util/parseAnimationValue.js +7 -1
  202. package/src/util/parseBoxShadowValue.js +72 -0
  203. package/src/util/parseDependency.js +37 -38
  204. package/src/util/parseGlob.js +24 -0
  205. package/src/util/pluginUtils.js +219 -219
  206. package/src/util/prefixSelector.js +30 -13
  207. package/src/util/removeAlphaVariables.js +24 -0
  208. package/src/util/resolveConfig.js +86 -91
  209. package/src/util/resolveConfigPath.js +12 -1
  210. package/src/util/splitAtTopLevelOnly.js +52 -0
  211. package/src/util/toPath.js +23 -1
  212. package/src/util/transformThemeValue.js +33 -8
  213. package/src/util/validateConfig.js +13 -0
  214. package/src/util/validateFormalSyntax.js +34 -0
  215. package/src/util/withAlphaVariable.js +14 -9
  216. package/stubs/.gitignore +1 -0
  217. package/stubs/.prettierrc.json +6 -0
  218. package/stubs/{defaultConfig.stub.js → config.full.js} +332 -249
  219. package/stubs/{simpleConfig.stub.js → config.simple.js} +0 -1
  220. package/stubs/postcss.config.js +6 -0
  221. package/stubs/tailwind.config.cjs +2 -0
  222. package/stubs/tailwind.config.js +2 -0
  223. package/stubs/tailwind.config.ts +3 -0
  224. package/types/config.d.ts +373 -0
  225. package/types/generated/.gitkeep +0 -0
  226. package/types/generated/colors.d.ts +298 -0
  227. package/types/generated/corePluginList.d.ts +1 -0
  228. package/types/generated/default-theme.d.ts +347 -0
  229. package/types/index.d.ts +7 -0
  230. package/CHANGELOG.md +0 -1742
  231. package/lib/constants.js +0 -37
  232. package/lib/lib/setupWatchingContext.js +0 -331
  233. package/nesting/plugin.js +0 -41
  234. package/scripts/install-integrations.js +0 -27
  235. package/scripts/rebuildFixtures.js +0 -68
  236. package/src/constants.js +0 -17
  237. package/src/lib/setupWatchingContext.js +0 -307
  238. /package/stubs/{defaultPostCssConfig.stub.js → postcss.config.cjs} +0 -0
@@ -1,27 +1,15 @@
1
+ import fs from 'fs'
2
+ import LRU from 'quick-lru'
1
3
  import * as sharedState from './sharedState'
2
4
  import { generateRules } from './generateRules'
3
- import bigSign from '../util/bigSign'
5
+ import log from '../util/log'
4
6
  import cloneNodes from '../util/cloneNodes'
7
+ import { defaultExtractor } from './defaultExtractor'
5
8
 
6
9
  let env = sharedState.env
7
- let contentMatchCache = sharedState.contentMatchCache
8
-
9
- const PATTERNS = [
10
- "([^<>\"'`\\s]*\\['[^<>\"'`\\s]*'\\])", // `content-['hello']` but not `content-['hello']']`
11
- '([^<>"\'`\\s]*\\["[^<>"\'`\\s]*"\\])', // `content-["hello"]` but not `content-["hello"]"]`
12
- '([^<>"\'`\\s]*\\[[^<>"\'`\\s]+\\])', // `fill-[#bada55]`
13
- '([^<>"\'`\\s]*[^<>"\'`\\s:])', // `px-1.5`, `uppercase` but not `uppercase:`
14
- ].join('|')
15
- const BROAD_MATCH_GLOBAL_REGEXP = new RegExp(PATTERNS, 'g')
16
- const INNER_MATCH_GLOBAL_REGEXP = /[^<>"'`\s.(){}[\]#=%]*[^<>"'`\s.(){}[\]#=%:]/g
17
10
 
18
11
  const builtInExtractors = {
19
- DEFAULT: (content) => {
20
- let broadMatches = content.match(BROAD_MATCH_GLOBAL_REGEXP) || []
21
- let innerMatches = content.match(INNER_MATCH_GLOBAL_REGEXP) || []
22
-
23
- return [...broadMatches, ...innerMatches]
24
- },
12
+ DEFAULT: defaultExtractor,
25
13
  }
26
14
 
27
15
  const builtInTransformers = {
@@ -29,41 +17,20 @@ const builtInTransformers = {
29
17
  svelte: (content) => content.replace(/(?:^|\s)class:/g, ' '),
30
18
  }
31
19
 
32
- function getExtractor(tailwindConfig, fileExtension) {
33
- let extractors = tailwindConfig.content.extract
34
- let contentOptions = tailwindConfig.content.options
35
-
36
- if (typeof extractors === 'function') {
37
- extractors = {
38
- DEFAULT: extractors,
39
- }
40
- }
41
- if (contentOptions.defaultExtractor) {
42
- extractors.DEFAULT = contentOptions.defaultExtractor
43
- }
44
- for (let { extensions, extractor } of contentOptions.extractors || []) {
45
- for (let extension of extensions) {
46
- extractors[extension] = extractor
47
- }
48
- }
20
+ function getExtractor(context, fileExtension) {
21
+ let extractors = context.tailwindConfig.content.extract
49
22
 
50
23
  return (
51
24
  extractors[fileExtension] ||
52
25
  extractors.DEFAULT ||
53
26
  builtInExtractors[fileExtension] ||
54
- builtInExtractors.DEFAULT
27
+ builtInExtractors.DEFAULT(context)
55
28
  )
56
29
  }
57
30
 
58
31
  function getTransformer(tailwindConfig, fileExtension) {
59
32
  let transformers = tailwindConfig.content.transform
60
33
 
61
- if (typeof transformers === 'function') {
62
- transformers = {
63
- DEFAULT: transformers,
64
- }
65
- }
66
-
67
34
  return (
68
35
  transformers[fileExtension] ||
69
36
  transformers.DEFAULT ||
@@ -72,10 +39,16 @@ function getTransformer(tailwindConfig, fileExtension) {
72
39
  )
73
40
  }
74
41
 
42
+ let extractorCache = new WeakMap()
43
+
75
44
  // Scans template contents for possible classes. This is a hot path on initial build but
76
45
  // not too important for subsequent builds. The faster the better though — if we can speed
77
46
  // up these regexes by 50% that could cut initial build time by like 20%.
78
- function getClassCandidates(content, extractor, contentMatchCache, candidates, seen) {
47
+ function getClassCandidates(content, extractor, candidates, seen) {
48
+ if (!extractorCache.has(extractor)) {
49
+ extractorCache.set(extractor, new LRU({ maxSize: 25000 }))
50
+ }
51
+
79
52
  for (let line of content.split('\n')) {
80
53
  line = line.trim()
81
54
 
@@ -84,8 +57,8 @@ function getClassCandidates(content, extractor, contentMatchCache, candidates, s
84
57
  }
85
58
  seen.add(line)
86
59
 
87
- if (contentMatchCache.has(line)) {
88
- for (let match of contentMatchCache.get(line)) {
60
+ if (extractorCache.get(extractor).has(line)) {
61
+ for (let match of extractorCache.get(extractor).get(line)) {
89
62
  candidates.add(match)
90
63
  }
91
64
  } else {
@@ -96,56 +69,29 @@ function getClassCandidates(content, extractor, contentMatchCache, candidates, s
96
69
  candidates.add(match)
97
70
  }
98
71
 
99
- contentMatchCache.set(line, lineMatchesSet)
72
+ extractorCache.get(extractor).set(line, lineMatchesSet)
100
73
  }
101
74
  }
102
75
  }
103
76
 
77
+ /**
78
+ *
79
+ * @param {[import('./offsets.js').RuleOffset, import('postcss').Node][]} rules
80
+ * @param {*} context
81
+ */
104
82
  function buildStylesheet(rules, context) {
105
- let sortedRules = rules.sort(([a], [z]) => bigSign(a - z))
83
+ let sortedRules = context.offsets.sort(rules)
106
84
 
107
85
  let returnValue = {
108
86
  base: new Set(),
87
+ defaults: new Set(),
109
88
  components: new Set(),
110
89
  utilities: new Set(),
111
90
  variants: new Set(),
112
-
113
- // All the CSS that is not Tailwind related can be put in this bucket. This
114
- // will make it easier to later use this information when we want to
115
- // `@apply` for example. The main reason we do this here is because we
116
- // still need to make sure the order is correct. Last but not least, we
117
- // will make sure to always re-inject this section into the css, even if
118
- // certain rules were not used. This means that it will look like a no-op
119
- // from the user's perspective, but we gathered all the useful information
120
- // we need.
121
- user: new Set(),
122
91
  }
123
92
 
124
93
  for (let [sort, rule] of sortedRules) {
125
- if (sort >= context.minimumScreen) {
126
- returnValue.variants.add(rule)
127
- continue
128
- }
129
-
130
- if (sort & context.layerOrder.base) {
131
- returnValue.base.add(rule)
132
- continue
133
- }
134
-
135
- if (sort & context.layerOrder.components) {
136
- returnValue.components.add(rule)
137
- continue
138
- }
139
-
140
- if (sort & context.layerOrder.utilities) {
141
- returnValue.utilities.add(rule)
142
- continue
143
- }
144
-
145
- if (sort & context.layerOrder.user) {
146
- returnValue.user.add(rule)
147
- continue
148
- }
94
+ returnValue[sort.layer].add(rule)
149
95
  }
150
96
 
151
97
  return returnValue
@@ -160,13 +106,15 @@ export default function expandTailwindAtRules(context) {
160
106
  variants: null,
161
107
  }
162
108
 
163
- // Make sure this file contains Tailwind directives. If not, we can save
164
- // a lot of work and bail early. Also we don't have to register our touch
165
- // file as a dependency since the output of this CSS does not depend on
166
- // the source of any templates. Think Vue <style> blocks for example.
167
- root.walkAtRules('tailwind', (rule) => {
168
- if (Object.keys(layerNodes).includes(rule.params)) {
169
- layerNodes[rule.params] = rule
109
+ root.walkAtRules((rule) => {
110
+ // Make sure this file contains Tailwind directives. If not, we can save
111
+ // a lot of work and bail early. Also we don't have to register our touch
112
+ // file as a dependency since the output of this CSS does not depend on
113
+ // the source of any templates. Think Vue <style> blocks for example.
114
+ if (rule.name === 'tailwind') {
115
+ if (Object.keys(layerNodes).includes(rule.params)) {
116
+ layerNodes[rule.params] = rule
117
+ }
170
118
  }
171
119
  })
172
120
 
@@ -177,38 +125,65 @@ export default function expandTailwindAtRules(context) {
177
125
  // ---
178
126
 
179
127
  // Find potential rules in changed files
180
- let candidates = new Set(['*'])
128
+ let candidates = new Set([...(context.candidates ?? []), sharedState.NOT_ON_DEMAND])
181
129
  let seen = new Set()
182
130
 
183
131
  env.DEBUG && console.time('Reading changed files')
184
132
 
185
- for (let { content, extension } of context.changedContent) {
186
- let transformer = getTransformer(context.tailwindConfig, extension)
187
- let extractor = getExtractor(context.tailwindConfig, extension)
188
- getClassCandidates(transformer(content), extractor, contentMatchCache, candidates, seen)
133
+ if (env.OXIDE) {
134
+ // TODO: Pass through or implement `extractor`
135
+ for (let candidate of require('@tailwindcss/oxide').parseCandidateStringsFromFiles(
136
+ context.changedContent
137
+ // Object.assign({}, builtInTransformers, context.tailwindConfig.content.transform)
138
+ )) {
139
+ candidates.add(candidate)
140
+ }
141
+
142
+ // for (let { file, content, extension } of context.changedContent) {
143
+ // let transformer = getTransformer(context.tailwindConfig, extension)
144
+ // let extractor = getExtractor(context, extension)
145
+ // getClassCandidatesOxide(file, transformer(content), extractor, candidates, seen)
146
+ // }
147
+ } else {
148
+ for (let { file, content, extension } of context.changedContent) {
149
+ let transformer = getTransformer(context.tailwindConfig, extension)
150
+ let extractor = getExtractor(context, extension)
151
+ content = file ? fs.readFileSync(file, 'utf8') : content
152
+ getClassCandidates(transformer(content), extractor, candidates, seen)
153
+ }
189
154
  }
190
155
 
156
+ env.DEBUG && console.timeEnd('Reading changed files')
157
+
191
158
  // ---
192
159
 
193
160
  // Generate the actual CSS
194
161
  let classCacheCount = context.classCache.size
195
162
 
196
163
  env.DEBUG && console.time('Generate rules')
197
- let rules = generateRules(candidates, context)
164
+ env.DEBUG && console.time('Sorting candidates')
165
+ let sortedCandidates = env.OXIDE
166
+ ? candidates
167
+ : new Set(
168
+ [...candidates].sort((a, z) => {
169
+ if (a === z) return 0
170
+ if (a < z) return -1
171
+ return 1
172
+ })
173
+ )
174
+ env.DEBUG && console.timeEnd('Sorting candidates')
175
+ generateRules(sortedCandidates, context)
198
176
  env.DEBUG && console.timeEnd('Generate rules')
199
177
 
200
178
  // We only ever add to the classCache, so if it didn't grow, there is nothing new.
201
179
  env.DEBUG && console.time('Build stylesheet')
202
180
  if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
203
- for (let rule of rules) {
204
- context.ruleCache.add(rule)
205
- }
206
-
207
181
  context.stylesheetCache = buildStylesheet([...context.ruleCache], context)
208
182
  }
209
183
  env.DEBUG && console.timeEnd('Build stylesheet')
210
184
 
211
185
  let {
186
+ defaults: defaultNodes,
212
187
  base: baseNodes,
213
188
  components: componentNodes,
214
189
  utilities: utilityNodes,
@@ -220,25 +195,72 @@ export default function expandTailwindAtRules(context) {
220
195
  // Replace any Tailwind directives with generated CSS
221
196
 
222
197
  if (layerNodes.base) {
223
- layerNodes.base.before(cloneNodes([...baseNodes], layerNodes.base.source))
198
+ layerNodes.base.before(
199
+ cloneNodes([...baseNodes, ...defaultNodes], layerNodes.base.source, {
200
+ layer: 'base',
201
+ })
202
+ )
224
203
  layerNodes.base.remove()
225
204
  }
226
205
 
227
206
  if (layerNodes.components) {
228
- layerNodes.components.before(cloneNodes([...componentNodes], layerNodes.components.source))
207
+ layerNodes.components.before(
208
+ cloneNodes([...componentNodes], layerNodes.components.source, {
209
+ layer: 'components',
210
+ })
211
+ )
229
212
  layerNodes.components.remove()
230
213
  }
231
214
 
232
215
  if (layerNodes.utilities) {
233
- layerNodes.utilities.before(cloneNodes([...utilityNodes], layerNodes.utilities.source))
216
+ layerNodes.utilities.before(
217
+ cloneNodes([...utilityNodes], layerNodes.utilities.source, {
218
+ layer: 'utilities',
219
+ })
220
+ )
234
221
  layerNodes.utilities.remove()
235
222
  }
236
223
 
224
+ // We do post-filtering to not alter the emitted order of the variants
225
+ const variantNodes = Array.from(screenNodes).filter((node) => {
226
+ const parentLayer = node.raws.tailwind?.parentLayer
227
+
228
+ if (parentLayer === 'components') {
229
+ return layerNodes.components !== null
230
+ }
231
+
232
+ if (parentLayer === 'utilities') {
233
+ return layerNodes.utilities !== null
234
+ }
235
+
236
+ return true
237
+ })
238
+
237
239
  if (layerNodes.variants) {
238
- layerNodes.variants.before(cloneNodes([...screenNodes], layerNodes.variants.source))
240
+ layerNodes.variants.before(
241
+ cloneNodes(variantNodes, layerNodes.variants.source, {
242
+ layer: 'variants',
243
+ })
244
+ )
239
245
  layerNodes.variants.remove()
240
- } else {
241
- root.append(cloneNodes([...screenNodes], root.source))
246
+ } else if (variantNodes.length > 0) {
247
+ root.append(
248
+ cloneNodes(variantNodes, root.source, {
249
+ layer: 'variants',
250
+ })
251
+ )
252
+ }
253
+
254
+ // If we've got a utility layer and no utilities are generated there's likely something wrong
255
+ const hasUtilityVariants = variantNodes.some(
256
+ (node) => node.raws.tailwind?.parentLayer === 'utilities'
257
+ )
258
+
259
+ if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
260
+ log.warn('content-problems', [
261
+ 'No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.',
262
+ 'https://tailwindcss.com/docs/content-configuration',
263
+ ])
242
264
  }
243
265
 
244
266
  // ---
@@ -246,7 +268,6 @@ export default function expandTailwindAtRules(context) {
246
268
  if (env.DEBUG) {
247
269
  console.log('Potential classes: ', candidates.size)
248
270
  console.log('Active contexts: ', sharedState.contextSourcesMap.size)
249
- console.log('Content match entries', contentMatchCache.size)
250
271
  }
251
272
 
252
273
  // Clear the cache for the changed files
@@ -0,0 +1,48 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+
4
+ /**
5
+ * Find the @config at-rule in the given CSS AST and return the relative path to the config file
6
+ *
7
+ * @param {import('postcss').Root} root
8
+ * @param {import('postcss').Result} result
9
+ */
10
+ export function findAtConfigPath(root, result) {
11
+ let configPath = null
12
+ let relativeTo = null
13
+
14
+ root.walkAtRules('config', (rule) => {
15
+ relativeTo = rule.source?.input.file ?? result.opts.from ?? null
16
+
17
+ if (relativeTo === null) {
18
+ throw rule.error(
19
+ 'The `@config` directive cannot be used without setting `from` in your PostCSS config.'
20
+ )
21
+ }
22
+
23
+ if (configPath) {
24
+ throw rule.error('Only one `@config` directive is allowed per file.')
25
+ }
26
+
27
+ let matches = rule.params.match(/(['"])(.*?)\1/)
28
+ if (!matches) {
29
+ throw rule.error('A path is required when using the `@config` directive.')
30
+ }
31
+
32
+ let inputPath = matches[2]
33
+ if (path.isAbsolute(inputPath)) {
34
+ throw rule.error('The `@config` directive cannot be used with an absolute path.')
35
+ }
36
+
37
+ configPath = path.resolve(path.dirname(relativeTo), inputPath)
38
+ if (!fs.existsSync(configPath)) {
39
+ throw rule.error(
40
+ `The config file at "${inputPath}" does not exist. Make sure the path is correct and the file exists.`
41
+ )
42
+ }
43
+
44
+ rule.remove()
45
+ })
46
+
47
+ return configPath ? configPath : null
48
+ }