tailwindcss 0.0.0-insiders.fe08e91 → 0.0.0-oxide.956419c

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 (186) hide show
  1. package/CHANGELOG.md +384 -3
  2. package/LICENSE +1 -2
  3. package/README.md +12 -8
  4. package/colors.d.ts +3 -0
  5. package/defaultConfig.d.ts +3 -0
  6. package/defaultTheme.d.ts +4 -0
  7. package/lib/cli/build/deps.js +54 -0
  8. package/lib/cli/build/index.js +48 -0
  9. package/lib/cli/build/plugin.js +367 -0
  10. package/lib/cli/build/utils.js +78 -0
  11. package/lib/cli/build/watching.js +178 -0
  12. package/lib/cli/help/index.js +71 -0
  13. package/lib/cli/index.js +239 -0
  14. package/lib/cli/init/index.js +46 -0
  15. package/lib/cli/shared.js +13 -0
  16. package/lib/cli-peer-dependencies.js +20 -7
  17. package/lib/cli.js +4 -740
  18. package/lib/constants.js +27 -20
  19. package/lib/corePluginList.js +6 -3
  20. package/lib/corePlugins.js +2064 -1811
  21. package/lib/css/preflight.css +5 -5
  22. package/lib/featureFlags.js +31 -22
  23. package/lib/index.js +4 -28
  24. package/lib/lib/cacheInvalidation.js +90 -0
  25. package/lib/lib/collapseAdjacentRules.js +27 -9
  26. package/lib/lib/collapseDuplicateDeclarations.js +12 -9
  27. package/lib/lib/content.js +176 -0
  28. package/lib/lib/defaultExtractor.js +225 -31
  29. package/lib/lib/detectNesting.js +13 -10
  30. package/lib/lib/evaluateTailwindFunctions.js +118 -55
  31. package/lib/lib/expandApplyAtRules.js +439 -190
  32. package/lib/lib/expandTailwindAtRules.js +151 -134
  33. package/lib/lib/findAtConfigPath.js +44 -0
  34. package/lib/lib/generateRules.js +454 -187
  35. package/lib/lib/getModuleDependencies.js +11 -8
  36. package/lib/lib/normalizeTailwindDirectives.js +36 -32
  37. package/lib/lib/offsets.js +217 -0
  38. package/lib/lib/partitionApplyAtRules.js +56 -0
  39. package/lib/lib/regex.js +60 -0
  40. package/lib/lib/resolveDefaultsAtRules.js +89 -67
  41. package/lib/lib/setupContextUtils.js +667 -376
  42. package/lib/lib/setupTrackingContext.js +38 -67
  43. package/lib/lib/sharedState.js +27 -14
  44. package/lib/lib/substituteScreenAtRules.js +11 -9
  45. package/lib/oxide/cli.d.js +1 -0
  46. package/lib/oxide/cli.js +2 -0
  47. package/lib/oxide/postcss-plugin.d.js +1 -0
  48. package/lib/oxide/postcss-plugin.js +2 -0
  49. package/lib/plugin.js +48 -0
  50. package/{nesting → lib/postcss-plugins/nesting}/README.md +2 -2
  51. package/lib/postcss-plugins/nesting/index.js +19 -0
  52. package/lib/postcss-plugins/nesting/plugin.js +87 -0
  53. package/lib/processTailwindFeatures.js +35 -25
  54. package/lib/public/colors.js +247 -245
  55. package/lib/public/create-plugin.js +6 -4
  56. package/lib/public/default-config.js +7 -5
  57. package/lib/public/default-theme.js +7 -5
  58. package/lib/public/resolve-config.js +8 -5
  59. package/lib/util/bigSign.js +4 -1
  60. package/lib/util/buildMediaQuery.js +11 -6
  61. package/lib/util/cloneDeep.js +7 -6
  62. package/lib/util/cloneNodes.js +21 -3
  63. package/lib/util/color.js +53 -54
  64. package/lib/util/configurePlugins.js +5 -2
  65. package/lib/util/createPlugin.js +6 -6
  66. package/lib/util/createUtilityPlugin.js +12 -14
  67. package/lib/util/dataTypes.js +119 -110
  68. package/lib/util/defaults.js +4 -1
  69. package/lib/util/escapeClassName.js +7 -4
  70. package/lib/util/escapeCommas.js +5 -2
  71. package/lib/util/flattenColorPalette.js +9 -12
  72. package/lib/util/formatVariantSelector.js +184 -85
  73. package/lib/util/getAllConfigs.js +27 -8
  74. package/lib/util/hashConfig.js +6 -3
  75. package/lib/util/isKeyframeRule.js +5 -2
  76. package/lib/util/isPlainObject.js +5 -2
  77. package/lib/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +23 -15
  78. package/lib/util/log.js +20 -14
  79. package/lib/util/nameClass.js +20 -9
  80. package/lib/util/negateValue.js +23 -8
  81. package/lib/util/normalizeConfig.js +116 -72
  82. package/lib/util/normalizeScreens.js +120 -11
  83. package/lib/util/parseAnimationValue.js +42 -40
  84. package/lib/util/parseBoxShadowValue.js +30 -23
  85. package/lib/util/parseDependency.js +38 -56
  86. package/lib/util/parseGlob.js +34 -0
  87. package/lib/util/parseObjectStyles.js +11 -8
  88. package/lib/util/pluginUtils.js +147 -50
  89. package/lib/util/prefixSelector.js +10 -8
  90. package/lib/util/removeAlphaVariables.js +29 -0
  91. package/lib/util/resolveConfig.js +97 -85
  92. package/lib/util/resolveConfigPath.js +11 -9
  93. package/lib/util/responsive.js +8 -5
  94. package/lib/util/splitAtTopLevelOnly.js +43 -0
  95. package/lib/util/tap.js +4 -1
  96. package/lib/util/toColorValue.js +5 -3
  97. package/lib/util/toPath.js +20 -4
  98. package/lib/util/transformThemeValue.js +37 -29
  99. package/lib/util/validateConfig.js +24 -0
  100. package/lib/util/validateFormalSyntax.js +24 -0
  101. package/lib/util/withAlphaVariable.js +23 -15
  102. package/nesting/index.js +2 -12
  103. package/package.json +50 -45
  104. package/peers/index.js +11381 -7950
  105. package/plugin.d.ts +11 -0
  106. package/resolveConfig.d.ts +12 -0
  107. package/scripts/generate-types.js +105 -0
  108. package/scripts/release-channel.js +18 -0
  109. package/scripts/release-notes.js +21 -0
  110. package/scripts/type-utils.js +27 -0
  111. package/src/cli/build/deps.js +56 -0
  112. package/src/cli/build/index.js +49 -0
  113. package/src/cli/build/plugin.js +439 -0
  114. package/src/cli/build/utils.js +76 -0
  115. package/src/cli/build/watching.js +227 -0
  116. package/src/cli/help/index.js +70 -0
  117. package/src/cli/index.js +234 -0
  118. package/src/cli/init/index.js +50 -0
  119. package/src/cli/shared.js +6 -0
  120. package/src/cli-peer-dependencies.js +7 -1
  121. package/src/cli.js +4 -810
  122. package/src/corePluginList.js +1 -1
  123. package/src/corePlugins.js +532 -217
  124. package/src/css/preflight.css +5 -5
  125. package/src/featureFlags.js +15 -9
  126. package/src/index.js +4 -27
  127. package/src/lib/cacheInvalidation.js +52 -0
  128. package/src/lib/collapseAdjacentRules.js +21 -2
  129. package/src/lib/content.js +212 -0
  130. package/src/lib/defaultExtractor.js +196 -33
  131. package/src/lib/evaluateTailwindFunctions.js +78 -7
  132. package/src/lib/expandApplyAtRules.js +482 -183
  133. package/src/lib/expandTailwindAtRules.js +106 -85
  134. package/src/lib/findAtConfigPath.js +48 -0
  135. package/src/lib/generateRules.js +418 -129
  136. package/src/lib/normalizeTailwindDirectives.js +1 -0
  137. package/src/lib/offsets.js +270 -0
  138. package/src/lib/partitionApplyAtRules.js +52 -0
  139. package/src/lib/regex.js +74 -0
  140. package/src/lib/resolveDefaultsAtRules.js +51 -30
  141. package/src/lib/setupContextUtils.js +556 -208
  142. package/src/lib/setupTrackingContext.js +11 -48
  143. package/src/lib/sharedState.js +5 -0
  144. package/src/oxide/cli.d.ts +0 -0
  145. package/src/oxide/cli.ts +1 -0
  146. package/src/oxide/postcss-plugin.d.ts +0 -0
  147. package/src/oxide/postcss-plugin.ts +1 -0
  148. package/src/plugin.js +47 -0
  149. package/src/postcss-plugins/nesting/README.md +42 -0
  150. package/src/postcss-plugins/nesting/index.js +13 -0
  151. package/src/postcss-plugins/nesting/plugin.js +80 -0
  152. package/src/processTailwindFeatures.js +8 -0
  153. package/src/util/buildMediaQuery.js +5 -3
  154. package/src/util/cloneNodes.js +19 -2
  155. package/src/util/color.js +25 -21
  156. package/src/util/dataTypes.js +29 -21
  157. package/src/util/formatVariantSelector.js +184 -61
  158. package/src/util/getAllConfigs.js +19 -0
  159. package/src/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +1 -1
  160. package/src/util/log.js +8 -8
  161. package/src/util/nameClass.js +4 -0
  162. package/src/util/negateValue.js +11 -3
  163. package/src/util/normalizeConfig.js +44 -6
  164. package/src/util/normalizeScreens.js +99 -4
  165. package/src/util/parseBoxShadowValue.js +4 -3
  166. package/src/util/parseDependency.js +37 -42
  167. package/src/util/parseGlob.js +24 -0
  168. package/src/util/pluginUtils.js +132 -10
  169. package/src/util/prefixSelector.js +7 -5
  170. package/src/util/removeAlphaVariables.js +24 -0
  171. package/src/util/resolveConfig.js +70 -32
  172. package/src/util/splitAtTopLevelOnly.js +45 -0
  173. package/src/util/toPath.js +1 -1
  174. package/src/util/transformThemeValue.js +13 -3
  175. package/src/util/validateConfig.js +13 -0
  176. package/src/util/validateFormalSyntax.js +34 -0
  177. package/src/util/withAlphaVariable.js +1 -1
  178. package/stubs/defaultConfig.stub.js +167 -164
  179. package/stubs/simpleConfig.stub.js +1 -0
  180. package/types/config.d.ts +362 -0
  181. package/types/generated/.gitkeep +0 -0
  182. package/types/generated/colors.d.ts +276 -0
  183. package/types/generated/corePluginList.d.ts +1 -0
  184. package/types/generated/default-theme.d.ts +342 -0
  185. package/types/index.d.ts +7 -0
  186. package/nesting/plugin.js +0 -41
@@ -1,10 +1,13 @@
1
+ import fs from 'fs'
1
2
  import LRU from 'quick-lru'
2
3
  import * as sharedState from './sharedState'
3
4
  import { generateRules } from './generateRules'
4
- import bigSign from '../util/bigSign'
5
+ import log from '../util/log'
5
6
  import cloneNodes from '../util/cloneNodes'
6
7
  import { defaultExtractor } from './defaultExtractor'
7
8
 
9
+ import oxide from '@tailwindcss/oxide'
10
+
8
11
  let env = sharedState.env
9
12
 
10
13
  const builtInExtractors = {
@@ -16,14 +19,14 @@ const builtInTransformers = {
16
19
  svelte: (content) => content.replace(/(?:^|\s)class:/g, ' '),
17
20
  }
18
21
 
19
- function getExtractor(tailwindConfig, fileExtension) {
20
- let extractors = tailwindConfig.content.extract
22
+ function getExtractor(context, fileExtension) {
23
+ let extractors = context.tailwindConfig.content.extract
21
24
 
22
25
  return (
23
26
  extractors[fileExtension] ||
24
27
  extractors.DEFAULT ||
25
28
  builtInExtractors[fileExtension] ||
26
- builtInExtractors.DEFAULT
29
+ builtInExtractors.DEFAULT(context)
27
30
  )
28
31
  }
29
32
 
@@ -73,8 +76,13 @@ function getClassCandidates(content, extractor, candidates, seen) {
73
76
  }
74
77
  }
75
78
 
79
+ /**
80
+ *
81
+ * @param {[import('./offsets.js').RuleOffset, import('postcss').Node][]} rules
82
+ * @param {*} context
83
+ */
76
84
  function buildStylesheet(rules, context) {
77
- let sortedRules = rules.sort(([a], [z]) => bigSign(a - z))
85
+ let sortedRules = context.offsets.sort(rules)
78
86
 
79
87
  let returnValue = {
80
88
  base: new Set(),
@@ -82,55 +90,15 @@ function buildStylesheet(rules, context) {
82
90
  components: new Set(),
83
91
  utilities: new Set(),
84
92
  variants: new Set(),
85
-
86
- // All the CSS that is not Tailwind related can be put in this bucket. This
87
- // will make it easier to later use this information when we want to
88
- // `@apply` for example. The main reason we do this here is because we
89
- // still need to make sure the order is correct. Last but not least, we
90
- // will make sure to always re-inject this section into the css, even if
91
- // certain rules were not used. This means that it will look like a no-op
92
- // from the user's perspective, but we gathered all the useful information
93
- // we need.
94
- user: new Set(),
95
93
  }
96
94
 
97
95
  for (let [sort, rule] of sortedRules) {
98
- if (sort >= context.minimumScreen) {
99
- returnValue.variants.add(rule)
100
- continue
101
- }
102
-
103
- if (sort & context.layerOrder.base) {
104
- returnValue.base.add(rule)
105
- continue
106
- }
107
-
108
- if (sort & context.layerOrder.defaults) {
109
- returnValue.defaults.add(rule)
110
- continue
111
- }
112
-
113
- if (sort & context.layerOrder.components) {
114
- returnValue.components.add(rule)
115
- continue
116
- }
117
-
118
- if (sort & context.layerOrder.utilities) {
119
- returnValue.utilities.add(rule)
120
- continue
121
- }
122
-
123
- if (sort & context.layerOrder.user) {
124
- returnValue.user.add(rule)
125
- continue
126
- }
96
+ returnValue[sort.layer].add(rule)
127
97
  }
128
98
 
129
99
  return returnValue
130
100
  }
131
101
 
132
- export const DEFAULTS_LAYER = Symbol('defaults-layer')
133
-
134
102
  export default function expandTailwindAtRules(context) {
135
103
  return (root) => {
136
104
  let layerNodes = {
@@ -140,8 +108,6 @@ export default function expandTailwindAtRules(context) {
140
108
  variants: null,
141
109
  }
142
110
 
143
- // let hasApply = false
144
-
145
111
  root.walkAtRules((rule) => {
146
112
  // Make sure this file contains Tailwind directives. If not, we can save
147
113
  // a lot of work and bail early. Also we don't have to register our touch
@@ -152,13 +118,6 @@ export default function expandTailwindAtRules(context) {
152
118
  layerNodes[rule.params] = rule
153
119
  }
154
120
  }
155
-
156
- // We also want to check for @apply because the user can
157
- // apply classes in an isolated environment like CSS
158
- // modules and we still need to inject defaults
159
- // if (rule.name === 'apply') {
160
- // hasApply = true
161
- // }
162
121
  })
163
122
 
164
123
  if (Object.values(layerNodes).every((n) => n === null)) {
@@ -168,33 +127,62 @@ export default function expandTailwindAtRules(context) {
168
127
  // ---
169
128
 
170
129
  // Find potential rules in changed files
171
- let candidates = new Set(['*'])
130
+ let candidates = new Set([...(context.candidates ?? []), sharedState.NOT_ON_DEMAND])
172
131
  let seen = new Set()
173
132
 
174
133
  env.DEBUG && console.time('Reading changed files')
175
134
 
176
- for (let { content, extension } of context.changedContent) {
177
- let transformer = getTransformer(context.tailwindConfig, extension)
178
- let extractor = getExtractor(context.tailwindConfig, extension)
179
- getClassCandidates(transformer(content), extractor, candidates, seen)
135
+ if (env.OXIDE) {
136
+ // TODO: Pass through or implement `extractor`
137
+ for (let candidate of oxide.parseCandidateStringsFromFiles(
138
+ context.changedContent
139
+ // Object.assign({}, builtInTransformers, context.tailwindConfig.content.transform)
140
+ )) {
141
+ candidates.add(candidate)
142
+ }
143
+
144
+ // for (let { file, content, extension } of context.changedContent) {
145
+ // let transformer = getTransformer(context.tailwindConfig, extension)
146
+ // let extractor = getExtractor(context, extension)
147
+ // getClassCandidatesOxide(file, transformer(content), extractor, candidates, seen)
148
+ // }
149
+ } else {
150
+ for (let { file, content, extension } of context.changedContent) {
151
+ let transformer = getTransformer(context.tailwindConfig, extension)
152
+ let extractor = getExtractor(context, extension)
153
+ content = file ? fs.readFileSync(file, 'utf8') : content
154
+ getClassCandidates(transformer(content), extractor, candidates, seen)
155
+ }
180
156
  }
181
157
 
158
+ env.DEBUG && console.timeEnd('Reading changed files')
159
+
182
160
  // ---
183
161
 
184
162
  // Generate the actual CSS
185
163
  let classCacheCount = context.classCache.size
186
164
 
187
165
  env.DEBUG && console.time('Generate rules')
188
- let rules = generateRules(candidates, context)
166
+ // TODO: Sorting is _probably_ slow, but right now it can guarantee the same order. Eventually
167
+ // we will be able to get rid of this.
168
+ env.DEBUG && console.time('Sorting candidates')
169
+ let sortedCandidates =
170
+ typeof process !== 'undefined' && process.env.JEST_WORKER_ID
171
+ ? new Set(
172
+ [...candidates].sort((a, z) => {
173
+ if (a === z) return 0
174
+ if (a < z) return -1
175
+ return 1
176
+ })
177
+ )
178
+ : candidates
179
+ env.DEBUG && console.timeEnd('Sorting candidates')
180
+ generateRules(sortedCandidates, context)
189
181
  env.DEBUG && console.timeEnd('Generate rules')
190
182
 
191
183
  // We only ever add to the classCache, so if it didn't grow, there is nothing new.
192
184
  env.DEBUG && console.time('Build stylesheet')
193
185
  if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
194
- for (let rule of rules) {
195
- context.ruleCache.add(rule)
196
- }
197
-
198
186
  context.stylesheetCache = buildStylesheet([...context.ruleCache], context)
199
187
  }
200
188
  env.DEBUG && console.timeEnd('Build stylesheet')
@@ -212,39 +200,72 @@ export default function expandTailwindAtRules(context) {
212
200
  // Replace any Tailwind directives with generated CSS
213
201
 
214
202
  if (layerNodes.base) {
215
- layerNodes.base.before(cloneNodes([...baseNodes], layerNodes.base.source))
216
- }
217
-
218
- // @defaults rules are unconditionally added first to ensure that
219
- // using any utility that relies on defaults will work even when
220
- // compiled in an isolated environment like CSS modules
221
- if (context.tailwindConfig[DEFAULTS_LAYER] !== false) {
222
- if (layerNodes.base) {
223
- layerNodes.base.after(cloneNodes([...defaultNodes], root.source))
224
- } else {
225
- root.prepend(cloneNodes([...defaultNodes], root.source))
226
- }
227
- }
228
-
229
- if (layerNodes.base) {
203
+ layerNodes.base.before(
204
+ cloneNodes([...baseNodes, ...defaultNodes], layerNodes.base.source, {
205
+ layer: 'base',
206
+ })
207
+ )
230
208
  layerNodes.base.remove()
231
209
  }
232
210
 
233
211
  if (layerNodes.components) {
234
- layerNodes.components.before(cloneNodes([...componentNodes], layerNodes.components.source))
212
+ layerNodes.components.before(
213
+ cloneNodes([...componentNodes], layerNodes.components.source, {
214
+ layer: 'components',
215
+ })
216
+ )
235
217
  layerNodes.components.remove()
236
218
  }
237
219
 
238
220
  if (layerNodes.utilities) {
239
- layerNodes.utilities.before(cloneNodes([...utilityNodes], layerNodes.utilities.source))
221
+ layerNodes.utilities.before(
222
+ cloneNodes([...utilityNodes], layerNodes.utilities.source, {
223
+ layer: 'utilities',
224
+ })
225
+ )
240
226
  layerNodes.utilities.remove()
241
227
  }
242
228
 
229
+ // We do post-filtering to not alter the emitted order of the variants
230
+ const variantNodes = Array.from(screenNodes).filter((node) => {
231
+ const parentLayer = node.raws.tailwind?.parentLayer
232
+
233
+ if (parentLayer === 'components') {
234
+ return layerNodes.components !== null
235
+ }
236
+
237
+ if (parentLayer === 'utilities') {
238
+ return layerNodes.utilities !== null
239
+ }
240
+
241
+ return true
242
+ })
243
+
243
244
  if (layerNodes.variants) {
244
- layerNodes.variants.before(cloneNodes([...screenNodes], layerNodes.variants.source))
245
+ layerNodes.variants.before(
246
+ cloneNodes(variantNodes, layerNodes.variants.source, {
247
+ layer: 'variants',
248
+ })
249
+ )
245
250
  layerNodes.variants.remove()
246
- } else {
247
- root.append(cloneNodes([...screenNodes], root.source))
251
+ } else if (variantNodes.length > 0) {
252
+ root.append(
253
+ cloneNodes(variantNodes, root.source, {
254
+ layer: 'variants',
255
+ })
256
+ )
257
+ }
258
+
259
+ // If we've got a utility layer and no utilities are generated there's likely something wrong
260
+ const hasUtilityVariants = variantNodes.some(
261
+ (node) => node.raws.tailwind?.parentLayer === 'utilities'
262
+ )
263
+
264
+ if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
265
+ log.warn('content-problems', [
266
+ 'No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.',
267
+ 'https://tailwindcss.com/docs/content-configuration',
268
+ ])
248
269
  }
249
270
 
250
271
  // ---
@@ -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
+ }