tailwindcss 0.0.0-insiders.ea139f2 → 0.0.0-insiders.ea4e1cd

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 (236) 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 -1
  5. package/defaultConfig.d.ts +3 -0
  6. package/defaultConfig.js +2 -1
  7. package/defaultTheme.d.ts +4 -0
  8. package/defaultTheme.js +2 -1
  9. package/lib/cli/build/deps.js +62 -0
  10. package/lib/cli/build/index.js +54 -0
  11. package/lib/cli/build/plugin.js +378 -0
  12. package/lib/cli/build/utils.js +88 -0
  13. package/lib/cli/build/watching.js +182 -0
  14. package/lib/cli/help/index.js +73 -0
  15. package/lib/cli/index.js +230 -0
  16. package/lib/cli/init/index.js +63 -0
  17. package/lib/cli-peer-dependencies.js +28 -7
  18. package/lib/cli.js +4 -703
  19. package/lib/corePluginList.js +12 -3
  20. package/lib/corePlugins.js +2373 -1863
  21. package/lib/css/preflight.css +10 -8
  22. package/lib/featureFlags.js +49 -26
  23. package/lib/index.js +1 -31
  24. package/lib/lib/cacheInvalidation.js +92 -0
  25. package/lib/lib/collapseAdjacentRules.js +30 -10
  26. package/lib/lib/collapseDuplicateDeclarations.js +60 -4
  27. package/lib/lib/content.js +181 -0
  28. package/lib/lib/defaultExtractor.js +243 -0
  29. package/lib/lib/detectNesting.js +21 -10
  30. package/lib/lib/evaluateTailwindFunctions.js +115 -50
  31. package/lib/lib/expandApplyAtRules.js +467 -161
  32. package/lib/lib/expandTailwindAtRules.js +160 -133
  33. package/lib/lib/findAtConfigPath.js +46 -0
  34. package/lib/lib/generateRules.js +553 -200
  35. package/lib/lib/getModuleDependencies.js +88 -37
  36. package/lib/lib/load-config.js +42 -0
  37. package/lib/lib/normalizeTailwindDirectives.js +46 -33
  38. package/lib/lib/offsets.js +306 -0
  39. package/lib/lib/partitionApplyAtRules.js +58 -0
  40. package/lib/lib/regex.js +74 -0
  41. package/lib/lib/remap-bitfield.js +89 -0
  42. package/lib/lib/resolveDefaultsAtRules.js +98 -58
  43. package/lib/lib/setupContextUtils.js +773 -321
  44. package/lib/lib/setupTrackingContext.js +70 -75
  45. package/lib/lib/sharedState.js +78 -10
  46. package/lib/lib/substituteScreenAtRules.js +14 -10
  47. package/lib/oxide/cli/build/deps.js +89 -0
  48. package/lib/oxide/cli/build/index.js +53 -0
  49. package/lib/oxide/cli/build/plugin.js +375 -0
  50. package/lib/oxide/cli/build/utils.js +87 -0
  51. package/lib/oxide/cli/build/watching.js +179 -0
  52. package/lib/oxide/cli/help/index.js +72 -0
  53. package/lib/oxide/cli/index.js +214 -0
  54. package/lib/oxide/cli/init/index.js +52 -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 +21 -0
  60. package/lib/postcss-plugins/nesting/plugin.js +89 -0
  61. package/lib/processTailwindFeatures.js +39 -26
  62. package/lib/public/colors.js +272 -246
  63. package/lib/public/create-plugin.js +9 -5
  64. package/lib/public/default-config.js +10 -6
  65. package/lib/public/default-theme.js +10 -6
  66. package/lib/public/load-config.js +12 -0
  67. package/lib/public/resolve-config.js +11 -6
  68. package/lib/util/applyImportantSelector.js +36 -0
  69. package/lib/util/bigSign.js +6 -1
  70. package/lib/util/buildMediaQuery.js +13 -6
  71. package/lib/util/cloneDeep.js +9 -6
  72. package/lib/util/cloneNodes.js +23 -3
  73. package/lib/util/color.js +70 -38
  74. package/lib/util/colorNames.js +752 -0
  75. package/lib/util/configurePlugins.js +7 -2
  76. package/lib/util/createPlugin.js +8 -6
  77. package/lib/util/createUtilityPlugin.js +16 -16
  78. package/lib/util/dataTypes.js +173 -108
  79. package/lib/util/defaults.js +14 -3
  80. package/lib/util/escapeClassName.js +13 -8
  81. package/lib/util/escapeCommas.js +7 -2
  82. package/lib/util/flattenColorPalette.js +11 -12
  83. package/lib/util/formatVariantSelector.js +228 -151
  84. package/lib/util/getAllConfigs.js +33 -12
  85. package/lib/util/hashConfig.js +9 -4
  86. package/lib/util/isKeyframeRule.js +7 -2
  87. package/lib/util/isPlainObject.js +7 -2
  88. package/lib/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +25 -15
  89. package/lib/util/log.js +27 -13
  90. package/lib/util/nameClass.js +27 -10
  91. package/lib/util/negateValue.js +25 -8
  92. package/lib/util/normalizeConfig.js +139 -65
  93. package/lib/util/normalizeScreens.js +131 -11
  94. package/lib/util/parseAnimationValue.js +44 -40
  95. package/lib/util/parseBoxShadowValue.js +34 -23
  96. package/lib/util/parseDependency.js +39 -55
  97. package/lib/util/parseGlob.js +36 -0
  98. package/lib/util/parseObjectStyles.js +15 -10
  99. package/lib/util/pluginUtils.js +159 -69
  100. package/lib/util/prefixSelector.js +30 -12
  101. package/lib/util/pseudoElements.js +229 -0
  102. package/lib/util/removeAlphaVariables.js +31 -0
  103. package/lib/util/resolveConfig.js +97 -75
  104. package/lib/util/resolveConfigPath.js +30 -12
  105. package/lib/util/responsive.js +11 -6
  106. package/lib/util/splitAtTopLevelOnly.js +51 -0
  107. package/lib/util/tap.js +6 -1
  108. package/lib/util/toColorValue.js +7 -3
  109. package/lib/util/toPath.js +26 -3
  110. package/lib/util/transformThemeValue.js +40 -30
  111. package/lib/util/validateConfig.js +37 -0
  112. package/lib/util/validateFormalSyntax.js +26 -0
  113. package/lib/util/withAlphaVariable.js +27 -15
  114. package/loadConfig.d.ts +4 -0
  115. package/loadConfig.js +2 -0
  116. package/nesting/index.js +2 -12
  117. package/package.json +66 -57
  118. package/peers/index.js +75964 -55560
  119. package/plugin.d.ts +11 -0
  120. package/plugin.js +2 -1
  121. package/resolveConfig.d.ts +12 -0
  122. package/resolveConfig.js +2 -1
  123. package/scripts/generate-types.js +105 -0
  124. package/scripts/release-channel.js +18 -0
  125. package/scripts/release-notes.js +21 -0
  126. package/scripts/swap-engines.js +40 -0
  127. package/scripts/type-utils.js +27 -0
  128. package/src/cli/build/deps.js +56 -0
  129. package/src/cli/build/index.js +49 -0
  130. package/src/cli/build/plugin.js +444 -0
  131. package/src/cli/build/utils.js +76 -0
  132. package/src/cli/build/watching.js +229 -0
  133. package/src/cli/help/index.js +70 -0
  134. package/src/cli/index.js +216 -0
  135. package/src/cli/init/index.js +79 -0
  136. package/src/cli-peer-dependencies.js +7 -1
  137. package/src/cli.js +4 -765
  138. package/src/corePluginList.js +1 -1
  139. package/src/corePlugins.js +786 -306
  140. package/src/css/preflight.css +10 -8
  141. package/src/featureFlags.js +21 -5
  142. package/src/index.js +1 -34
  143. package/src/lib/cacheInvalidation.js +52 -0
  144. package/src/lib/collapseAdjacentRules.js +21 -2
  145. package/src/lib/collapseDuplicateDeclarations.js +66 -1
  146. package/src/lib/content.js +208 -0
  147. package/src/lib/defaultExtractor.js +217 -0
  148. package/src/lib/detectNesting.js +9 -1
  149. package/src/lib/evaluateTailwindFunctions.js +79 -8
  150. package/src/lib/expandApplyAtRules.js +515 -153
  151. package/src/lib/expandTailwindAtRules.js +115 -86
  152. package/src/lib/findAtConfigPath.js +48 -0
  153. package/src/lib/generateRules.js +545 -147
  154. package/src/lib/getModuleDependencies.js +70 -30
  155. package/src/lib/load-config.ts +31 -0
  156. package/src/lib/normalizeTailwindDirectives.js +7 -1
  157. package/src/lib/offsets.js +373 -0
  158. package/src/lib/partitionApplyAtRules.js +52 -0
  159. package/src/lib/regex.js +74 -0
  160. package/src/lib/remap-bitfield.js +82 -0
  161. package/src/lib/resolveDefaultsAtRules.js +59 -17
  162. package/src/lib/setupContextUtils.js +701 -175
  163. package/src/lib/setupTrackingContext.js +51 -62
  164. package/src/lib/sharedState.js +58 -7
  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 +12 -2
  180. package/src/public/colors.js +22 -0
  181. package/src/public/default-config.js +1 -1
  182. package/src/public/default-theme.js +2 -2
  183. package/src/public/load-config.js +2 -0
  184. package/src/util/applyImportantSelector.js +27 -0
  185. package/src/util/buildMediaQuery.js +5 -3
  186. package/src/util/cloneNodes.js +19 -2
  187. package/src/util/color.js +44 -12
  188. package/src/util/colorNames.js +150 -0
  189. package/src/util/dataTypes.js +51 -16
  190. package/src/util/defaults.js +6 -0
  191. package/src/util/formatVariantSelector.js +264 -144
  192. package/src/util/getAllConfigs.js +21 -2
  193. package/src/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +1 -1
  194. package/src/util/log.js +11 -7
  195. package/src/util/nameClass.js +4 -0
  196. package/src/util/negateValue.js +11 -3
  197. package/src/util/normalizeConfig.js +57 -5
  198. package/src/util/normalizeScreens.js +105 -7
  199. package/src/util/parseBoxShadowValue.js +4 -3
  200. package/src/util/parseDependency.js +37 -42
  201. package/src/util/parseGlob.js +24 -0
  202. package/src/util/pluginUtils.js +123 -24
  203. package/src/util/prefixSelector.js +30 -10
  204. package/src/util/pseudoElements.js +170 -0
  205. package/src/util/removeAlphaVariables.js +24 -0
  206. package/src/util/resolveConfig.js +74 -26
  207. package/src/util/resolveConfigPath.js +12 -1
  208. package/src/util/splitAtTopLevelOnly.js +52 -0
  209. package/src/util/toPath.js +23 -1
  210. package/src/util/transformThemeValue.js +13 -3
  211. package/src/util/validateConfig.js +26 -0
  212. package/src/util/validateFormalSyntax.js +34 -0
  213. package/src/util/withAlphaVariable.js +1 -1
  214. package/stubs/.gitignore +1 -0
  215. package/stubs/.prettierrc.json +6 -0
  216. package/stubs/{defaultConfig.stub.js → config.full.js} +206 -166
  217. package/stubs/postcss.config.js +6 -0
  218. package/stubs/tailwind.config.cjs +2 -0
  219. package/stubs/tailwind.config.js +2 -0
  220. package/stubs/tailwind.config.ts +3 -0
  221. package/types/config.d.ts +368 -0
  222. package/types/generated/.gitkeep +0 -0
  223. package/types/generated/colors.d.ts +298 -0
  224. package/types/generated/corePluginList.d.ts +1 -0
  225. package/types/generated/default-theme.d.ts +371 -0
  226. package/types/index.d.ts +7 -0
  227. package/CHANGELOG.md +0 -1843
  228. package/lib/constants.js +0 -37
  229. package/lib/lib/setupWatchingContext.js +0 -288
  230. package/nesting/plugin.js +0 -41
  231. package/scripts/install-integrations.js +0 -27
  232. package/scripts/rebuildFixtures.js +0 -68
  233. package/src/constants.js +0 -17
  234. package/src/lib/setupWatchingContext.js +0 -311
  235. /package/stubs/{simpleConfig.stub.js → config.simple.js} +0 -0
  236. /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,3 +1,11 @@
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
@@ -5,7 +13,7 @@ export default function (_context) {
5
13
  root.walkAtRules('tailwind', (node) => {
6
14
  if (found) return false
7
15
 
8
- if (node.parent && node.parent.type !== 'root') {
16
+ if (node.parent && !(isRoot(node.parent) || isAtLayer(node.parent))) {
9
17
  found = true
10
18
  node.warn(
11
19
  result,
@@ -5,6 +5,9 @@ import parseValue from 'postcss-value-parser'
5
5
  import { normalizeScreens } from '../util/normalizeScreens'
6
6
  import buildMediaQuery from '../util/buildMediaQuery'
7
7
  import { toPath } from '../util/toPath'
8
+ import { withAlphaValue } from '../util/withAlphaVariable'
9
+ import { parseColorFormat } from '../util/pluginUtils'
10
+ import log from '../util/log'
8
11
 
9
12
  function isObject(input) {
10
13
  return typeof input === 'object' && input !== null
@@ -37,12 +40,10 @@ function listKeys(obj) {
37
40
  return list(Object.keys(obj))
38
41
  }
39
42
 
40
- function validatePath(config, path, defaultValue) {
41
- const pathString = Array.isArray(path)
42
- ? pathToString(path)
43
- : path.replace(/^['"]+/g, '').replace(/['"]+$/g, '')
43
+ function validatePath(config, path, defaultValue, themeOpts = {}) {
44
+ const pathString = Array.isArray(path) ? pathToString(path) : path.replace(/^['"]+|['"]+$/g, '')
44
45
  const pathSegments = Array.isArray(path) ? path : toPath(pathString)
45
- const value = dlv(config.theme, pathString, defaultValue)
46
+ const value = dlv(config.theme, pathSegments, defaultValue)
46
47
 
47
48
  if (value === undefined) {
48
49
  let error = `'${pathString}' does not exist in your theme config.`
@@ -114,7 +115,7 @@ function validatePath(config, path, defaultValue) {
114
115
 
115
116
  return {
116
117
  isValid: true,
117
- value: transformThemeValue(themeSection)(value),
118
+ value: transformThemeValue(themeSection)(value, themeOpts),
118
119
  }
119
120
  }
120
121
 
@@ -157,19 +158,89 @@ let nodeTypePropertyMap = {
157
158
  decl: 'value',
158
159
  }
159
160
 
160
- 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
+
161
203
  let functions = {
162
204
  theme: (node, path, ...defaultValue) => {
163
- const { isValid, value, error } = validatePath(
205
+ let { isValid, value, error, alpha } = resolvePath(
164
206
  config,
165
207
  path,
166
208
  defaultValue.length ? defaultValue : undefined
167
209
  )
168
210
 
169
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
+
170
230
  throw node.error(error)
171
231
  }
172
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
+
173
244
  return value
174
245
  },
175
246
  screen: (node, screen) => {