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
@@ -0,0 +1,217 @@
1
+ import { flagEnabled } from '../featureFlags'
2
+ import * as regex from './regex'
3
+
4
+ export function defaultExtractor(context) {
5
+ let patterns = Array.from(buildRegExps(context))
6
+
7
+ /**
8
+ * @param {string} content
9
+ */
10
+ return (content) => {
11
+ /** @type {(string|string)[]} */
12
+ let results = []
13
+
14
+ for (let pattern of patterns) {
15
+ results = [...results, ...(content.match(pattern) ?? [])]
16
+ }
17
+
18
+ return results.filter((v) => v !== undefined).map(clipAtBalancedParens)
19
+ }
20
+ }
21
+
22
+ function* buildRegExps(context) {
23
+ let separator = context.tailwindConfig.separator
24
+ let variantGroupingEnabled = flagEnabled(context.tailwindConfig, 'variantGrouping')
25
+ let prefix =
26
+ context.tailwindConfig.prefix !== ''
27
+ ? regex.optional(regex.pattern([/-?/, regex.escape(context.tailwindConfig.prefix)]))
28
+ : ''
29
+
30
+ let utility = regex.any([
31
+ // Arbitrary properties (without square brackets)
32
+ /\[[^\s:'"`]+:[^\s\[\]]+\]/,
33
+
34
+ // Arbitrary properties with balanced square brackets
35
+ // This is a targeted fix to continue to allow theme()
36
+ // with square brackets to work in arbitrary properties
37
+ // while fixing a problem with the regex matching too much
38
+ /\[[^\s:'"`]+:[^\s]+?\[[^\s]+?\][^\s]+?\]/,
39
+
40
+ // Utilities
41
+ regex.pattern([
42
+ // Utility Name / Group Name
43
+ /-?(?:\w+)/,
44
+
45
+ // Normal/Arbitrary values
46
+ regex.optional(
47
+ regex.any([
48
+ regex.pattern([
49
+ // Arbitrary values
50
+ /-(?:\w+-)*\[[^\s:]+\]/,
51
+
52
+ // Not immediately followed by an `{[(`
53
+ /(?![{([]])/,
54
+
55
+ // optionally followed by an opacity modifier
56
+ /(?:\/[^\s'"`\\><$]*)?/,
57
+ ]),
58
+
59
+ regex.pattern([
60
+ // Arbitrary values
61
+ /-(?:\w+-)*\[[^\s]+\]/,
62
+
63
+ // Not immediately followed by an `{[(`
64
+ /(?![{([]])/,
65
+
66
+ // optionally followed by an opacity modifier
67
+ /(?:\/[^\s'"`\\$]*)?/,
68
+ ]),
69
+
70
+ // Normal values w/o quotes — may include an opacity modifier
71
+ /[-\/][^\s'"`\\$={><]*/,
72
+ ])
73
+ ),
74
+ ]),
75
+ ])
76
+
77
+ let variantPatterns = [
78
+ // Without quotes
79
+ regex.any([
80
+ // This is here to provide special support for the `@` variant
81
+ regex.pattern([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/, separator]),
82
+
83
+ regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
84
+ regex.pattern([/[^\s"'`\[\\]+/, separator]),
85
+ ]),
86
+
87
+ // With quotes allowed
88
+ regex.any([
89
+ regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
90
+ regex.pattern([/[^\s`\[\\]+/, separator]),
91
+ ]),
92
+ ]
93
+
94
+ for (const variantPattern of variantPatterns) {
95
+ yield regex.pattern([
96
+ // Variants
97
+ '((?=((',
98
+ variantPattern,
99
+ ')+))\\2)?',
100
+
101
+ // Important (optional)
102
+ /!?/,
103
+
104
+ prefix,
105
+
106
+ variantGroupingEnabled
107
+ ? regex.any([
108
+ // Or any of those things but grouped separated by commas
109
+ regex.pattern([/\(/, utility, regex.zeroOrMore([/,/, utility]), /\)/]),
110
+
111
+ // Arbitrary properties, constrained utilities, arbitrary values, etc…
112
+ utility,
113
+ ])
114
+ : utility,
115
+ ])
116
+ }
117
+
118
+ // 5. Inner matches
119
+ yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
120
+ }
121
+
122
+ // We want to capture any "special" characters
123
+ // AND the characters immediately following them (if there is one)
124
+ let SPECIALS = /([\[\]'"`])([^\[\]'"`])?/g
125
+ let ALLOWED_CLASS_CHARACTERS = /[^"'`\s<>\]]+/
126
+
127
+ /**
128
+ * Clips a string ensuring that parentheses, quotes, etc… are balanced
129
+ * Used for arbitrary values only
130
+ *
131
+ * We will go past the end of the balanced parens until we find a non-class character
132
+ *
133
+ * Depth matching behavior:
134
+ * w-[calc(100%-theme('spacing[some_key][1.5]'))]']
135
+ * ┬ ┬ ┬┬ ┬ ┬┬ ┬┬┬┬┬┬┬
136
+ * 1 2 3 4 34 3 210 END
137
+ * ╰────┴──────────┴────────┴────────┴┴───┴─┴┴┴
138
+ *
139
+ * @param {string} input
140
+ */
141
+ function clipAtBalancedParens(input) {
142
+ // We are care about this for arbitrary values
143
+ if (!input.includes('-[')) {
144
+ return input
145
+ }
146
+
147
+ let depth = 0
148
+ let openStringTypes = []
149
+
150
+ // Find all parens, brackets, quotes, etc
151
+ // Stop when we end at a balanced pair
152
+ // This is naive and will treat mismatched parens as balanced
153
+ // This shouldn't be a problem in practice though
154
+ let matches = input.matchAll(SPECIALS)
155
+
156
+ // We can't use lookbehind assertions because we have to support Safari
157
+ // So, instead, we've emulated it using capture groups and we'll re-work the matches to accommodate
158
+ matches = Array.from(matches).flatMap((match) => {
159
+ const [, ...groups] = match
160
+
161
+ return groups.map((group, idx) =>
162
+ Object.assign([], match, {
163
+ index: match.index + idx,
164
+ 0: group,
165
+ })
166
+ )
167
+ })
168
+
169
+ for (let match of matches) {
170
+ let char = match[0]
171
+ let inStringType = openStringTypes[openStringTypes.length - 1]
172
+
173
+ if (char === inStringType) {
174
+ openStringTypes.pop()
175
+ } else if (char === "'" || char === '"' || char === '`') {
176
+ openStringTypes.push(char)
177
+ }
178
+
179
+ if (inStringType) {
180
+ continue
181
+ } else if (char === '[') {
182
+ depth++
183
+ continue
184
+ } else if (char === ']') {
185
+ depth--
186
+ continue
187
+ }
188
+
189
+ // We've gone one character past the point where we should stop
190
+ // This means that there was an extra closing `]`
191
+ // We'll clip to just before it
192
+ if (depth < 0) {
193
+ return input.substring(0, match.index - 1)
194
+ }
195
+
196
+ // We've finished balancing the brackets but there still may be characters that can be included
197
+ // For example in the class `text-[#336699]/[.35]`
198
+ // The depth goes to `0` at the closing `]` but goes up again at the `[`
199
+
200
+ // If we're at zero and encounter a non-class character then we clip the class there
201
+ if (depth === 0 && !ALLOWED_CLASS_CHARACTERS.test(char)) {
202
+ return input.substring(0, match.index)
203
+ }
204
+ }
205
+
206
+ return input
207
+ }
208
+
209
+ // Regular utilities
210
+ // {{modifier}:}*{namespace}{-{suffix}}*{/{opacityModifier}}?
211
+
212
+ // Arbitrary values
213
+ // {{modifier}:}*{namespace}-[{arbitraryValue}]{/{opacityModifier}}?
214
+ // arbitraryValue: no whitespace, balanced quotes unless within quotes, balanced brackets unless within quotes
215
+
216
+ // Arbitrary properties
217
+ // {{modifier}:}*[{validCssPropertyName}:{arbitraryValue}]
@@ -1,7 +1,32 @@
1
+ function isRoot(node) {
2
+ return node.type === 'root'
3
+ }
4
+
5
+ function isAtLayer(node) {
6
+ return node.type === 'atrule' && node.name === 'layer'
7
+ }
8
+
1
9
  export default function (_context) {
2
10
  return (root, result) => {
3
11
  let found = false
4
12
 
13
+ root.walkAtRules('tailwind', (node) => {
14
+ if (found) return false
15
+
16
+ if (node.parent && !(isRoot(node.parent) || isAtLayer(node.parent))) {
17
+ found = true
18
+ node.warn(
19
+ result,
20
+ [
21
+ 'Nested @tailwind rules were detected, but are not supported.',
22
+ "Consider using a prefix to scope Tailwind's classes: https://tailwindcss.com/docs/configuration#prefix",
23
+ 'Alternatively, use the important selector strategy: https://tailwindcss.com/docs/configuration#selector-strategy',
24
+ ].join('\n')
25
+ )
26
+ return false
27
+ }
28
+ })
29
+
5
30
  root.walkRules((rule) => {
6
31
  if (found) return false
7
32
 
@@ -9,10 +34,12 @@ export default function (_context) {
9
34
  found = true
10
35
  nestedRule.warn(
11
36
  result,
12
- // TODO: Improve this warning message
13
- 'Nested CSS detected, checkout the docs on how to support nesting: https://tailwindcss.com/docs/using-with-preprocessors#nesting'
37
+ [
38
+ 'Nested CSS was detected, but CSS nesting has not been configured correctly.',
39
+ 'Please enable a CSS nesting plugin *before* Tailwind in your configuration.',
40
+ 'See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting',
41
+ ].join('\n')
14
42
  )
15
-
16
43
  return false
17
44
  })
18
45
  })
@@ -2,8 +2,12 @@ import dlv from 'dlv'
2
2
  import didYouMean from 'didyoumean'
3
3
  import transformThemeValue from '../util/transformThemeValue'
4
4
  import parseValue from 'postcss-value-parser'
5
+ import { normalizeScreens } from '../util/normalizeScreens'
5
6
  import buildMediaQuery from '../util/buildMediaQuery'
6
7
  import { toPath } from '../util/toPath'
8
+ import { withAlphaValue } from '../util/withAlphaVariable'
9
+ import { parseColorFormat } from '../util/pluginUtils'
10
+ import log from '../util/log'
7
11
 
8
12
  function isObject(input) {
9
13
  return typeof input === 'object' && input !== null
@@ -36,12 +40,10 @@ function listKeys(obj) {
36
40
  return list(Object.keys(obj))
37
41
  }
38
42
 
39
- function validatePath(config, path, defaultValue) {
40
- const pathString = Array.isArray(path)
41
- ? pathToString(path)
42
- : path.replace(/^['"]+/g, '').replace(/['"]+$/g, '')
43
+ function validatePath(config, path, defaultValue, themeOpts = {}) {
44
+ const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, '')
43
45
  const pathSegments = Array.isArray(path) ? path : toPath(pathString)
44
- const value = dlv(config.theme, pathString, defaultValue)
46
+ const value = dlv(config.theme, pathSegments, defaultValue)
45
47
 
46
48
  if (value === undefined) {
47
49
  let error = `'${pathString}' does not exist in your theme config.`
@@ -113,7 +115,7 @@ function validatePath(config, path, defaultValue) {
113
115
 
114
116
  return {
115
117
  isValid: true,
116
- value: transformThemeValue(themeSection)(value),
118
+ value: transformThemeValue(themeSection)(value, themeOpts),
117
119
  }
118
120
  }
119
121
 
@@ -156,29 +158,101 @@ let nodeTypePropertyMap = {
156
158
  decl: 'value',
157
159
  }
158
160
 
159
- export default function ({ tailwindConfig: config }) {
161
+ /**
162
+ * @param {string} path
163
+ * @returns {Iterable<[path: string, alpha: string|undefined]>}
164
+ */
165
+ function* toPaths(path) {
166
+ // Strip quotes from beginning and end of string
167
+ // This allows the alpha value to be present inside of quotes
168
+ path = path.replace(/^['"]+|['"]+$/g, '')
169
+
170
+ let matches = path.match(/^([^\s]+)(?![^\[]*\])(?:\s*\/\s*([^\/\s]+))$/)
171
+ let alpha = undefined
172
+
173
+ yield [path, undefined]
174
+
175
+ if (matches) {
176
+ path = matches[1]
177
+ alpha = matches[2]
178
+
179
+ yield [path, alpha]
180
+ }
181
+ }
182
+
183
+ /**
184
+ *
185
+ * @param {any} config
186
+ * @param {string} path
187
+ * @param {any} defaultValue
188
+ */
189
+ function resolvePath(config, path, defaultValue) {
190
+ const results = Array.from(toPaths(path)).map(([path, alpha]) => {
191
+ return Object.assign(validatePath(config, path, defaultValue, { opacityValue: alpha }), {
192
+ resolvedPath: path,
193
+ alpha,
194
+ })
195
+ })
196
+
197
+ return results.find((result) => result.isValid) ?? results[0]
198
+ }
199
+
200
+ export default function (context) {
201
+ let config = context.tailwindConfig
202
+
160
203
  let functions = {
161
204
  theme: (node, path, ...defaultValue) => {
162
- const { isValid, value, error } = validatePath(
205
+ let { isValid, value, error, alpha } = resolvePath(
163
206
  config,
164
207
  path,
165
208
  defaultValue.length ? defaultValue : undefined
166
209
  )
167
210
 
168
211
  if (!isValid) {
212
+ let parentNode = node.parent
213
+ let candidate = parentNode?.raws.tailwind?.candidate
214
+
215
+ if (parentNode && candidate !== undefined) {
216
+ // Remove this utility from any caches
217
+ context.markInvalidUtilityNode(parentNode)
218
+
219
+ // Remove the CSS node from the markup
220
+ parentNode.remove()
221
+
222
+ // Show a warning
223
+ log.warn('invalid-theme-key-in-class', [
224
+ `The utility \`${candidate}\` contains an invalid theme value and was not generated.`,
225
+ ])
226
+
227
+ return
228
+ }
229
+
169
230
  throw node.error(error)
170
231
  }
171
232
 
233
+ let maybeColor = parseColorFormat(value)
234
+ let isColorFunction = maybeColor !== undefined && typeof maybeColor === 'function'
235
+
236
+ if (alpha !== undefined || isColorFunction) {
237
+ if (alpha === undefined) {
238
+ alpha = 1.0
239
+ }
240
+
241
+ value = withAlphaValue(maybeColor, alpha, maybeColor)
242
+ }
243
+
172
244
  return value
173
245
  },
174
246
  screen: (node, screen) => {
175
247
  screen = screen.replace(/^['"]+/g, '').replace(/['"]+$/g, '')
248
+ let screens = normalizeScreens(config.theme.screens)
249
+ let screenDefinition = screens.find(({ name }) => name === screen)
176
250
 
177
- if (config.theme.screens[screen] === undefined) {
251
+ if (!screenDefinition) {
178
252
  throw node.error(`The '${screen}' screen does not exist in your theme.`)
179
253
  }
180
254
 
181
- return buildMediaQuery(config.theme.screens[screen])
255
+ return buildMediaQuery(screenDefinition)
182
256
  },
183
257
  }
184
258
  return (root) => {