tailwindcss 3.3.2 → 3.3.3

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 (48) hide show
  1. package/CHANGELOG.md +26 -1
  2. package/lib/cli/build/plugin.js +2 -2
  3. package/lib/corePlugins.js +11 -7
  4. package/lib/css/preflight.css +9 -0
  5. package/lib/lib/evaluateTailwindFunctions.js +5 -3
  6. package/lib/lib/expandTailwindAtRules.js +4 -4
  7. package/lib/lib/generateRules.js +15 -7
  8. package/lib/lib/setupContextUtils.js +24 -6
  9. package/lib/lib/setupTrackingContext.js +2 -1
  10. package/lib/plugin.js +3 -3
  11. package/lib/processTailwindFeatures.js +2 -2
  12. package/lib/util/dataTypes.js +14 -6
  13. package/lib/util/formatVariantSelector.js +2 -2
  14. package/lib/util/prefixSelector.js +1 -1
  15. package/lib/util/pseudoElements.js +18 -34
  16. package/lib/value-parser/LICENSE +22 -0
  17. package/lib/value-parser/README.md +3 -0
  18. package/lib/value-parser/index.d.js +2 -0
  19. package/lib/value-parser/index.js +22 -0
  20. package/lib/value-parser/parse.js +259 -0
  21. package/lib/value-parser/stringify.js +38 -0
  22. package/lib/value-parser/unit.js +86 -0
  23. package/lib/value-parser/walk.js +16 -0
  24. package/package.json +1 -2
  25. package/src/cli/build/plugin.js +2 -2
  26. package/src/corePlugins.js +13 -7
  27. package/src/css/preflight.css +9 -0
  28. package/src/lib/evaluateTailwindFunctions.js +4 -1
  29. package/src/lib/expandTailwindAtRules.js +9 -7
  30. package/src/lib/generateRules.js +15 -8
  31. package/src/lib/setupContextUtils.js +18 -5
  32. package/src/lib/setupTrackingContext.js +1 -3
  33. package/src/plugin.js +3 -3
  34. package/src/processTailwindFeatures.js +3 -2
  35. package/src/util/dataTypes.js +17 -6
  36. package/src/util/formatVariantSelector.js +2 -2
  37. package/src/util/prefixSelector.js +1 -0
  38. package/src/util/pseudoElements.js +14 -17
  39. package/src/value-parser/LICENSE +22 -0
  40. package/src/value-parser/README.md +3 -0
  41. package/src/value-parser/index.d.ts +177 -0
  42. package/src/value-parser/index.js +28 -0
  43. package/src/value-parser/parse.js +303 -0
  44. package/src/value-parser/stringify.js +41 -0
  45. package/src/value-parser/unit.js +118 -0
  46. package/src/value-parser/walk.js +18 -0
  47. package/stubs/config.full.js +1 -0
  48. package/types/generated/default-theme.d.ts +1 -0
@@ -24,6 +24,8 @@ import { Offsets } from './offsets.js'
24
24
  import { flagEnabled } from '../featureFlags.js'
25
25
  import { finalizeSelector, formatVariantSelector } from '../util/formatVariantSelector'
26
26
 
27
+ export const INTERNAL_FEATURES = Symbol()
28
+
27
29
  const VARIANT_TYPES = {
28
30
  AddVariant: Symbol.for('ADD_VARIANT'),
29
31
  MatchVariant: Symbol.for('MATCH_VARIANT'),
@@ -230,8 +232,8 @@ export function parseVariant(variant) {
230
232
  return ({ format }) => format(str)
231
233
  }
232
234
 
233
- let [, name, params] = /@(.*?)( .+|[({].*)/g.exec(str)
234
- return ({ wrap }) => wrap(postcss.atRule({ name, params: params.trim() }))
235
+ let [, name, params] = /@(\S*)( .+|[({].*)?/g.exec(str)
236
+ return ({ wrap }) => wrap(postcss.atRule({ name, params: params?.trim() ?? '' }))
235
237
  })
236
238
  .reverse()
237
239
 
@@ -949,7 +951,11 @@ function registerPlugins(plugins, context) {
949
951
  let idx = BigInt(parasiteUtilities.length)
950
952
 
951
953
  for (const [, rule] of rules) {
952
- sortedClassNames.set(rule.raws.tailwind.candidate, idx++)
954
+ let candidate = rule.raws.tailwind.candidate
955
+
956
+ // When multiple rules match a candidate
957
+ // always take the position of the first one
958
+ sortedClassNames.set(candidate, sortedClassNames.get(candidate) ?? idx++)
953
959
  }
954
960
 
955
961
  return classes.map((className) => {
@@ -1119,17 +1125,24 @@ function registerPlugins(plugins, context) {
1119
1125
  }
1120
1126
 
1121
1127
  let isArbitraryVariant = !(value in (options.values ?? {}))
1128
+ let internalFeatures = options[INTERNAL_FEATURES] ?? {}
1129
+
1130
+ let respectPrefix = (() => {
1131
+ if (isArbitraryVariant) return false
1132
+ if (internalFeatures.respectPrefix === false) return false
1133
+ return true
1134
+ })()
1122
1135
 
1123
1136
  formatStrings = formatStrings.map((format) =>
1124
1137
  format.map((str) => ({
1125
1138
  format: str,
1126
- isArbitraryVariant,
1139
+ respectPrefix,
1127
1140
  }))
1128
1141
  )
1129
1142
 
1130
1143
  manualFormatStrings = manualFormatStrings.map((format) => ({
1131
1144
  format,
1132
- isArbitraryVariant,
1145
+ respectPrefix,
1133
1146
  }))
1134
1147
 
1135
1148
  let opts = {
@@ -63,9 +63,7 @@ function getTailwindConfig(configOrPath) {
63
63
  }
64
64
 
65
65
  // It's a plain object, not a path
66
- let newConfig = resolveConfig(
67
- configOrPath.config === undefined ? configOrPath : configOrPath.config
68
- )
66
+ let newConfig = resolveConfig(configOrPath?.config ?? configOrPath ?? {})
69
67
 
70
68
  newConfig = validateConfig(newConfig)
71
69
 
package/src/plugin.js CHANGED
@@ -13,7 +13,7 @@ module.exports = function tailwindcss(configOrPath) {
13
13
  console.time('JIT TOTAL')
14
14
  return root
15
15
  },
16
- function (root, result) {
16
+ async function (root, result) {
17
17
  // Use the path for the `@config` directive if it exists, otherwise use the
18
18
  // path for the file being processed
19
19
  configOrPath = findAtConfigPath(root, result) ?? configOrPath
@@ -25,14 +25,14 @@ module.exports = function tailwindcss(configOrPath) {
25
25
 
26
26
  for (const root of roots) {
27
27
  if (root.type === 'root') {
28
- processTailwindFeatures(context)(root, result)
28
+ await processTailwindFeatures(context)(root, result)
29
29
  }
30
30
  }
31
31
 
32
32
  return
33
33
  }
34
34
 
35
- processTailwindFeatures(context)(root, result)
35
+ await processTailwindFeatures(context)(root, result)
36
36
  },
37
37
  __OXIDE__ &&
38
38
  function lightningCssPlugin(_root, result) {
@@ -12,7 +12,7 @@ import { createContext } from './lib/setupContextUtils'
12
12
  import { issueFlagNotices } from './featureFlags'
13
13
 
14
14
  export default function processTailwindFeatures(setupContext) {
15
- return function (root, result) {
15
+ return async function (root, result) {
16
16
  let { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root)
17
17
 
18
18
  detectNesting()(root, result)
@@ -44,7 +44,8 @@ export default function processTailwindFeatures(setupContext) {
44
44
 
45
45
  issueFlagNotices(context.tailwindConfig)
46
46
 
47
- expandTailwindAtRules(context)(root, result)
47
+ await expandTailwindAtRules(context)(root, result)
48
+
48
49
  // Partition apply rules that are generated by
49
50
  // addComponents, addUtilities and so on.
50
51
  partitionApplyAtRules()(root, result)
@@ -49,10 +49,22 @@ export function normalize(value, isRoot = true) {
49
49
  value = value.trim()
50
50
  }
51
51
 
52
- // Add spaces around operators inside math functions like calc() that do not follow an operator
53
- // or '('.
54
- value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
52
+ value = normalizeMathOperatorSpacing(value)
53
+
54
+ return value
55
+ }
56
+
57
+ /**
58
+ * Add spaces around operators inside math functions
59
+ * like calc() that do not follow an operator or '('.
60
+ *
61
+ * @param {string} value
62
+ * @returns {string}
63
+ */
64
+ function normalizeMathOperatorSpacing(value) {
65
+ return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
55
66
  let vars = []
67
+
56
68
  return match
57
69
  .replace(/var\((--.+?)[,)]/g, (match, g1) => {
58
70
  vars.push(g1)
@@ -61,8 +73,6 @@ export function normalize(value, isRoot = true) {
61
73
  .replace(/(-?\d*\.?\d(?!\b-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 ')
62
74
  .replace(placeholderRe, () => vars.shift())
63
75
  })
64
-
65
- return value
66
76
  }
67
77
 
68
78
  export function url(value) {
@@ -178,11 +188,12 @@ export function image(value) {
178
188
  }
179
189
 
180
190
  let gradientTypes = new Set([
191
+ 'conic-gradient',
181
192
  'linear-gradient',
182
193
  'radial-gradient',
194
+ 'repeating-conic-gradient',
183
195
  'repeating-linear-gradient',
184
196
  'repeating-radial-gradient',
185
- 'conic-gradient',
186
197
  ])
187
198
  export function gradient(value) {
188
199
  value = normalize(value)
@@ -9,7 +9,7 @@ import { movePseudos } from './pseudoElements'
9
9
  /** @typedef {import('postcss-selector-parser').Pseudo} Pseudo */
10
10
  /** @typedef {import('postcss-selector-parser').Node} Node */
11
11
 
12
- /** @typedef {{format: string, isArbitraryVariant: boolean}[]} RawFormats */
12
+ /** @typedef {{format: string, respectPrefix: boolean}[]} RawFormats */
13
13
  /** @typedef {import('postcss-selector-parser').Root} ParsedFormats */
14
14
  /** @typedef {RawFormats | ParsedFormats} AcceptedFormats */
15
15
 
@@ -29,7 +29,7 @@ export function formatVariantSelector(formats, { context, candidate }) {
29
29
 
30
30
  return {
31
31
  ...format,
32
- ast: format.isArbitraryVariant ? ast : prefixSelector(prefix, ast),
32
+ ast: format.respectPrefix ? prefixSelector(prefix, ast) : ast,
33
33
  }
34
34
  })
35
35
 
@@ -17,6 +17,7 @@ export default function (prefix, selector, prependNegative = false) {
17
17
  return selector
18
18
  }
19
19
 
20
+ /** @type {import('postcss-selector-parser').Root} */
20
21
  let ast = typeof selector === 'string' ? parser().astSync(selector) : selector
21
22
 
22
23
  ast.walkClasses((classSelector) => {
@@ -19,40 +19,37 @@
19
19
  // **Jumpable**
20
20
  // Any terminal element may "jump" over combinators when moving to the end of the selector
21
21
  //
22
- // This is a backwards-compat quirk of :before and :after variants.
22
+ // This is a backwards-compat quirk of pseudo element variants from earlier versions of Tailwind CSS.
23
23
 
24
24
  /** @typedef {'terminal' | 'actionable' | 'jumpable'} PseudoProperty */
25
25
 
26
26
  /** @type {Record<string, PseudoProperty[]>} */
27
27
  let elementProperties = {
28
+ // Pseudo elements from the spec
28
29
  '::after': ['terminal', 'jumpable'],
29
- '::backdrop': ['terminal'],
30
+ '::backdrop': ['terminal', 'jumpable'],
30
31
  '::before': ['terminal', 'jumpable'],
31
32
  '::cue': ['terminal'],
32
33
  '::cue-region': ['terminal'],
33
34
  '::first-letter': ['terminal', 'jumpable'],
34
35
  '::first-line': ['terminal', 'jumpable'],
35
36
  '::grammar-error': ['terminal'],
36
- '::marker': ['terminal'],
37
+ '::marker': ['terminal', 'jumpable'],
37
38
  '::part': ['terminal', 'actionable'],
38
- '::placeholder': ['terminal'],
39
- '::selection': ['terminal'],
39
+ '::placeholder': ['terminal', 'jumpable'],
40
+ '::selection': ['terminal', 'jumpable'],
40
41
  '::slotted': ['terminal'],
41
42
  '::spelling-error': ['terminal'],
42
43
  '::target-text': ['terminal'],
43
44
 
44
- // other
45
+ // Pseudo elements from the spec with special rules
45
46
  '::file-selector-button': ['terminal', 'actionable'],
46
- '::-webkit-progress-bar': ['terminal', 'actionable'],
47
47
 
48
- // Webkit scroll bar pseudo elements can be combined with user-action pseudo classes
49
- '::-webkit-scrollbar': ['terminal', 'actionable'],
50
- '::-webkit-scrollbar-button': ['terminal', 'actionable'],
51
- '::-webkit-scrollbar-thumb': ['terminal', 'actionable'],
52
- '::-webkit-scrollbar-track': ['terminal', 'actionable'],
53
- '::-webkit-scrollbar-track-piece': ['terminal', 'actionable'],
54
- '::-webkit-scrollbar-corner': ['terminal', 'actionable'],
55
- '::-webkit-resizer': ['terminal', 'actionable'],
48
+ // Library-specific pseudo elements used by component libraries
49
+ // These are Shadow DOM-like
50
+ '::deep': ['actionable'],
51
+ '::v-deep': ['actionable'],
52
+ '::ng-deep': ['actionable'],
56
53
 
57
54
  // Note: As a rule, double colons (::) should be used instead of a single colon
58
55
  // (:). This distinguishes pseudo-classes from pseudo-elements. However, since
@@ -65,8 +62,8 @@ let elementProperties = {
65
62
 
66
63
  // The default value is used when the pseudo-element is not recognized
67
64
  // Because it's not recognized, we don't know if it's terminal or not
68
- // So we assume it can't be moved AND can have user-action pseudo classes attached to it
69
- __default__: ['actionable'],
65
+ // So we assume it can be moved AND can have user-action pseudo classes attached to it
66
+ __default__: ['terminal', 'actionable'],
70
67
  }
71
68
 
72
69
  /**
@@ -0,0 +1,22 @@
1
+ Copyright (c) Bogdan Chadkin <trysound@yandex.ru>
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ # postcss-value-parser (forked + inlined)
2
+
3
+ This is a customized version of of [PostCSS Value Parser](https://github.com/TrySound/postcss-value-parser) to fix some bugs around parsing CSS functions.
@@ -0,0 +1,177 @@
1
+ declare namespace postcssValueParser {
2
+ interface BaseNode {
3
+ /**
4
+ * The offset, inclusive, inside the CSS value at which the node starts.
5
+ */
6
+ sourceIndex: number
7
+
8
+ /**
9
+ * The offset, exclusive, inside the CSS value at which the node ends.
10
+ */
11
+ sourceEndIndex: number
12
+
13
+ /**
14
+ * The node's characteristic value
15
+ */
16
+ value: string
17
+ }
18
+
19
+ interface ClosableNode {
20
+ /**
21
+ * Whether the parsed CSS value ended before the node was properly closed
22
+ */
23
+ unclosed?: true
24
+ }
25
+
26
+ interface AdjacentAwareNode {
27
+ /**
28
+ * The token at the start of the node
29
+ */
30
+ before: string
31
+
32
+ /**
33
+ * The token at the end of the node
34
+ */
35
+ after: string
36
+ }
37
+
38
+ interface CommentNode extends BaseNode, ClosableNode {
39
+ type: 'comment'
40
+ }
41
+
42
+ interface DivNode extends BaseNode, AdjacentAwareNode {
43
+ type: 'div'
44
+ }
45
+
46
+ interface FunctionNode extends BaseNode, ClosableNode, AdjacentAwareNode {
47
+ type: 'function'
48
+
49
+ /**
50
+ * Nodes inside the function
51
+ */
52
+ nodes: Node[]
53
+ }
54
+
55
+ interface SpaceNode extends BaseNode {
56
+ type: 'space'
57
+ }
58
+
59
+ interface StringNode extends BaseNode, ClosableNode {
60
+ type: 'string'
61
+
62
+ /**
63
+ * The quote type delimiting the string
64
+ */
65
+ quote: '"' | "'"
66
+ }
67
+
68
+ interface UnicodeRangeNode extends BaseNode {
69
+ type: 'unicode-range'
70
+ }
71
+
72
+ interface WordNode extends BaseNode {
73
+ type: 'word'
74
+ }
75
+
76
+ /**
77
+ * Any node parsed from a CSS value
78
+ */
79
+ type Node =
80
+ | CommentNode
81
+ | DivNode
82
+ | FunctionNode
83
+ | SpaceNode
84
+ | StringNode
85
+ | UnicodeRangeNode
86
+ | WordNode
87
+
88
+ interface CustomStringifierCallback {
89
+ /**
90
+ * @param node The node to stringify
91
+ * @returns The serialized CSS representation of the node
92
+ */
93
+ (nodes: Node): string | undefined
94
+ }
95
+
96
+ interface WalkCallback {
97
+ /**
98
+ * @param node The currently visited node
99
+ * @param index The index of the node in the series of parsed nodes
100
+ * @param nodes The series of parsed nodes
101
+ * @returns Returning `false` will prevent traversal of descendant nodes (only applies if `bubble` was set to `true` in the `walk()` call)
102
+ */
103
+ (node: Node, index: number, nodes: Node[]): void | boolean
104
+ }
105
+
106
+ /**
107
+ * A CSS dimension, decomposed into its numeric and unit parts
108
+ */
109
+ interface Dimension {
110
+ number: string
111
+ unit: string
112
+ }
113
+
114
+ /**
115
+ * A wrapper around a parsed CSS value that allows for inspecting and walking nodes
116
+ */
117
+ interface ParsedValue {
118
+ /**
119
+ * The series of parsed nodes
120
+ */
121
+ nodes: Node[]
122
+
123
+ /**
124
+ * Walk all parsed nodes, applying a callback
125
+ *
126
+ * @param callback A visitor callback that will be executed for each node
127
+ * @param bubble When set to `true`, walking will be done inside-out instead of outside-in
128
+ */
129
+ walk(callback: WalkCallback, bubble?: boolean): this
130
+ }
131
+
132
+ interface ValueParser {
133
+ /**
134
+ * Decompose a CSS dimension into its numeric and unit part
135
+ *
136
+ * @param value The dimension to decompose
137
+ * @returns An object representing `number` and `unit` part of the dimension or `false` if the decomposing fails
138
+ */
139
+ unit(value: string): Dimension | false
140
+
141
+ /**
142
+ * Serialize a series of nodes into a CSS value
143
+ *
144
+ * @param nodes The nodes to stringify
145
+ * @param custom A custom stringifier callback
146
+ * @returns The generated CSS value
147
+ */
148
+ stringify(nodes: Node | Node[], custom?: CustomStringifierCallback): string
149
+
150
+ /**
151
+ * Walk a series of nodes, applying a callback
152
+ *
153
+ * @param nodes The nodes to walk
154
+ * @param callback A visitor callback that will be executed for each node
155
+ * @param bubble When set to `true`, walking will be done inside-out instead of outside-in
156
+ */
157
+ walk(nodes: Node[], callback: WalkCallback, bubble?: boolean): void
158
+
159
+ /**
160
+ * Parse a CSS value into a series of nodes to operate on
161
+ *
162
+ * @param value The value to parse
163
+ */
164
+ new (value: string): ParsedValue
165
+
166
+ /**
167
+ * Parse a CSS value into a series of nodes to operate on
168
+ *
169
+ * @param value The value to parse
170
+ */
171
+ (value: string): ParsedValue
172
+ }
173
+ }
174
+
175
+ declare const postcssValueParser: postcssValueParser.ValueParser
176
+
177
+ export = postcssValueParser
@@ -0,0 +1,28 @@
1
+ var parse = require('./parse')
2
+ var walk = require('./walk')
3
+ var stringify = require('./stringify')
4
+
5
+ function ValueParser(value) {
6
+ if (this instanceof ValueParser) {
7
+ this.nodes = parse(value)
8
+ return this
9
+ }
10
+ return new ValueParser(value)
11
+ }
12
+
13
+ ValueParser.prototype.toString = function () {
14
+ return Array.isArray(this.nodes) ? stringify(this.nodes) : ''
15
+ }
16
+
17
+ ValueParser.prototype.walk = function (cb, bubble) {
18
+ walk(this.nodes, cb, bubble)
19
+ return this
20
+ }
21
+
22
+ ValueParser.unit = require('./unit')
23
+
24
+ ValueParser.walk = walk
25
+
26
+ ValueParser.stringify = stringify
27
+
28
+ module.exports = ValueParser