tailwindcss 0.0.0-insiders.9d83400 → 0.0.0-insiders.9dcd97a

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.
@@ -237,14 +237,14 @@ let state = {
237
237
  return content;
238
238
  },
239
239
  getContext ({ createContext, cliConfigPath, root, result, content }) {
240
- if (this.context) {
241
- this.context.changedContent = this.changedContent.splice(0);
242
- return this.context;
243
- }
244
240
  _sharedState.env.DEBUG && console.time('Searching for config');
245
241
  var _findAtConfigPath1;
246
242
  let configPath = (_findAtConfigPath1 = (0, _findAtConfigPath.findAtConfigPath)(root, result)) !== null && _findAtConfigPath1 !== void 0 ? _findAtConfigPath1 : cliConfigPath;
247
243
  _sharedState.env.DEBUG && console.timeEnd('Searching for config');
244
+ if (this.context) {
245
+ this.context.changedContent = this.changedContent.splice(0);
246
+ return this.context;
247
+ }
248
248
  _sharedState.env.DEBUG && console.time('Loading config');
249
249
  let config = this.loadConfig(configPath, content);
250
250
  _sharedState.env.DEBUG && console.timeEnd('Loading config');
@@ -32,6 +32,7 @@ const _default = [
32
32
  "lineClamp",
33
33
  "display",
34
34
  "aspectRatio",
35
+ "size",
35
36
  "height",
36
37
  "maxHeight",
37
38
  "minHeight",
@@ -184,5 +185,6 @@ const _default = [
184
185
  "transitionDuration",
185
186
  "transitionTimingFunction",
186
187
  "willChange",
187
- "content"
188
+ "content",
189
+ "forcedColorAdjust"
188
190
  ];
@@ -82,6 +82,9 @@ function _interop_require_wildcard(obj, nodeInterop) {
82
82
  return newObj;
83
83
  }
84
84
  let variantPlugins = {
85
+ childVariant: ({ addVariant })=>{
86
+ addVariant('*', '& > *');
87
+ },
85
88
  pseudoElementVariants: ({ addVariant })=>{
86
89
  addVariant('first-letter', '&::first-letter');
87
90
  addVariant('first-line', '&::first-line');
@@ -265,15 +268,15 @@ let variantPlugins = {
265
268
  }
266
269
  },
267
270
  directionVariants: ({ addVariant })=>{
268
- addVariant('ltr', ':is([dir="ltr"] &)');
269
- addVariant('rtl', ':is([dir="rtl"] &)');
271
+ addVariant('ltr', '&:where([dir="ltr"], [dir="ltr"] *)');
272
+ addVariant('rtl', '&:where([dir="rtl"], [dir="rtl"] *)');
270
273
  },
271
274
  reducedMotionVariants: ({ addVariant })=>{
272
275
  addVariant('motion-safe', '@media (prefers-reduced-motion: no-preference)');
273
276
  addVariant('motion-reduce', '@media (prefers-reduced-motion: reduce)');
274
277
  },
275
278
  darkVariants: ({ config, addVariant })=>{
276
- let [mode, className = '.dark'] = [].concat(config('darkMode', 'media'));
279
+ let [mode, selector = '.dark'] = [].concat(config('darkMode', 'media'));
277
280
  if (mode === false) {
278
281
  mode = 'media';
279
282
  _log.default.warn('darkmode-false', [
@@ -282,10 +285,48 @@ let variantPlugins = {
282
285
  'https://tailwindcss.com/docs/upgrade-guide#remove-dark-mode-configuration'
283
286
  ]);
284
287
  }
285
- if (mode === 'class') {
286
- addVariant('dark', `:is(${className} &)`);
288
+ if (mode === 'variant') {
289
+ let formats;
290
+ if (Array.isArray(selector)) {
291
+ formats = selector;
292
+ } else if (typeof selector === 'function') {
293
+ formats = selector;
294
+ } else if (typeof selector === 'string') {
295
+ formats = [
296
+ selector
297
+ ];
298
+ }
299
+ // TODO: We could also add these warnings if the user passes a function that returns string | string[]
300
+ // But this is an advanced enough use case that it's probably not necessary
301
+ if (Array.isArray(formats)) {
302
+ for (let format of formats){
303
+ if (format === '.dark') {
304
+ mode = false;
305
+ _log.default.warn('darkmode-variant-without-selector', [
306
+ 'When using `variant` for `darkMode`, you must provide a selector.',
307
+ 'Example: `darkMode: ["variant", ".your-selector &"]`'
308
+ ]);
309
+ } else if (!format.includes('&')) {
310
+ mode = false;
311
+ _log.default.warn('darkmode-variant-without-ampersand', [
312
+ 'When using `variant` for `darkMode`, your selector must contain `&`.',
313
+ 'Example `darkMode: ["variant", ".your-selector &"]`'
314
+ ]);
315
+ }
316
+ }
317
+ }
318
+ selector = formats;
319
+ }
320
+ if (mode === 'selector') {
321
+ // New preferred behavior
322
+ addVariant('dark', `&:where(${selector}, ${selector} *)`);
287
323
  } else if (mode === 'media') {
288
324
  addVariant('dark', '@media (prefers-color-scheme: dark)');
325
+ } else if (mode === 'variant') {
326
+ addVariant('dark', selector);
327
+ } else if (mode === 'class') {
328
+ // Old behavior
329
+ addVariant('dark', `:is(${selector} &)`);
289
330
  }
290
331
  },
291
332
  printVariant: ({ addVariant })=>{
@@ -466,6 +507,9 @@ let variantPlugins = {
466
507
  prefersContrastVariants: ({ addVariant })=>{
467
508
  addVariant('contrast-more', '@media (prefers-contrast: more)');
468
509
  addVariant('contrast-less', '@media (prefers-contrast: less)');
510
+ },
511
+ forcedColorsVariants: ({ addVariant })=>{
512
+ addVariant('forced-colors', '@media (forced-colors: active)');
469
513
  }
470
514
  };
471
515
  let cssTransformValue = [
@@ -781,6 +825,12 @@ let corePlugins = {
781
825
  ]),
782
826
  float: ({ addUtilities })=>{
783
827
  addUtilities({
828
+ '.float-start': {
829
+ float: 'inline-start'
830
+ },
831
+ '.float-end': {
832
+ float: 'inline-end'
833
+ },
784
834
  '.float-right': {
785
835
  float: 'right'
786
836
  },
@@ -794,6 +844,12 @@ let corePlugins = {
794
844
  },
795
845
  clear: ({ addUtilities })=>{
796
846
  addUtilities({
847
+ '.clear-start': {
848
+ clear: 'inline-start'
849
+ },
850
+ '.clear-end': {
851
+ clear: 'inline-end'
852
+ },
797
853
  '.clear-left': {
798
854
  clear: 'left'
799
855
  },
@@ -977,6 +1033,15 @@ let corePlugins = {
977
1033
  ]
978
1034
  ]
979
1035
  ]),
1036
+ size: (0, _createUtilityPlugin.default)('size', [
1037
+ [
1038
+ 'size',
1039
+ [
1040
+ 'width',
1041
+ 'height'
1042
+ ]
1043
+ ]
1044
+ ]),
980
1045
  height: (0, _createUtilityPlugin.default)('height', [
981
1046
  [
982
1047
  'h',
@@ -1620,6 +1685,9 @@ let corePlugins = {
1620
1685
  addUtilities({
1621
1686
  '.appearance-none': {
1622
1687
  appearance: 'none'
1688
+ },
1689
+ '.appearance-auto': {
1690
+ appearance: 'auto'
1623
1691
  }
1624
1692
  });
1625
1693
  },
@@ -4196,5 +4264,15 @@ let corePlugins = {
4196
4264
  ]
4197
4265
  ]
4198
4266
  ]
4199
- ])
4267
+ ]),
4268
+ forcedColorAdjust: ({ addUtilities })=>{
4269
+ addUtilities({
4270
+ '.forced-color-adjust-auto': {
4271
+ 'forced-color-adjust': 'auto'
4272
+ },
4273
+ '.forced-color-adjust-none': {
4274
+ 'forced-color-adjust': 'none'
4275
+ }
4276
+ });
4277
+ }
4200
4278
  };
@@ -24,6 +24,7 @@
24
24
  4. Use the user's configured `sans` font-family by default.
25
25
  5. Use the user's configured `sans` font-feature-settings by default.
26
26
  6. Use the user's configured `sans` font-variation-settings by default.
27
+ 7. Disable tap highlights on iOS.
27
28
  */
28
29
 
29
30
  html,
@@ -35,6 +36,7 @@ html,
35
36
  font-family: theme('fontFamily.sans', ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); /* 4 */
36
37
  font-feature-settings: theme('fontFamily.sans[1].fontFeatureSettings', normal); /* 5 */
37
38
  font-variation-settings: theme('fontFamily.sans[1].fontVariationSettings', normal); /* 6 */
39
+ -webkit-tap-highlight-color: transparent; /* 7 */
38
40
  }
39
41
 
40
42
  /*
@@ -100,8 +102,10 @@ strong {
100
102
  }
101
103
 
102
104
  /*
103
- 1. Use the user's configured `mono` font family by default.
104
- 2. Correct the odd `em` font sizing in all browsers.
105
+ 1. Use the user's configured `mono` font-family by default.
106
+ 2. Use the user's configured `mono` font-feature-settings by default.
107
+ 3. Use the user's configured `mono` font-variation-settings by default.
108
+ 4. Correct the odd `em` font sizing in all browsers.
105
109
  */
106
110
 
107
111
  code,
@@ -109,7 +113,9 @@ kbd,
109
113
  samp,
110
114
  pre {
111
115
  font-family: theme('fontFamily.mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); /* 1 */
112
- font-size: 1em; /* 2 */
116
+ font-feature-settings: theme('fontFamily.mono[1].fontFeatureSettings', normal); /* 2 */
117
+ font-variation-settings: theme('fontFamily.mono[1].fontVariationSettings', normal); /* 3 */
118
+ font-size: 1em; /* 4 */
113
119
  }
114
120
 
115
121
  /*
@@ -21,7 +21,6 @@ const _fs = /*#__PURE__*/ _interop_require_default(require("fs"));
21
21
  const _path = /*#__PURE__*/ _interop_require_default(require("path"));
22
22
  const _isglob = /*#__PURE__*/ _interop_require_default(require("is-glob"));
23
23
  const _fastglob = /*#__PURE__*/ _interop_require_default(require("fast-glob"));
24
- const _normalizepath = /*#__PURE__*/ _interop_require_default(require("normalize-path"));
25
24
  const _parseGlob = require("../util/parseGlob");
26
25
  const _sharedState = require("./sharedState");
27
26
  const _oxide = require("@tailwindcss/oxide");
@@ -30,6 +29,37 @@ function _interop_require_default(obj) {
30
29
  default: obj
31
30
  };
32
31
  }
32
+ /*!
33
+ * Modified version of normalize-path, original license below
34
+ *
35
+ * normalize-path <https://github.com/jonschlinkert/normalize-path>
36
+ *
37
+ * Copyright (c) 2014-2018, Jon Schlinkert.
38
+ * Released under the MIT License.
39
+ */ function normalizePath(path) {
40
+ if (typeof path !== 'string') {
41
+ throw new TypeError('expected path to be a string');
42
+ }
43
+ if (path === '\\' || path === '/') return '/';
44
+ var len = path.length;
45
+ if (len <= 1) return path;
46
+ // ensure that win32 namespaces has two leading slashes, so that the path is
47
+ // handled properly by the win32 version of path.parse() after being normalized
48
+ // https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces
49
+ var prefix = '';
50
+ if (len > 4 && path[3] === '\\') {
51
+ var ch = path[2];
52
+ if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') {
53
+ path = path.slice(2);
54
+ prefix = '//';
55
+ }
56
+ }
57
+ // Modified part: instead of purely splitting on `\\` and `/`, we split on
58
+ // `/` and `\\` that is _not_ followed by any of the following characters: ()[]
59
+ // This is to ensure that we keep the escaping of brackets and parentheses
60
+ let segs = path.split(/[/\\]+(?![\(\)\[\]])/);
61
+ return prefix + segs.join('/');
62
+ }
33
63
  /** @typedef {import('../../types/config.js').RawFile} RawFile */ /** @typedef {import('../../types/config.js').FilePath} FilePath */ /*
34
64
  * @param {import('tailwindcss').Config} tailwindConfig
35
65
  * @param {{skip:string[]}} options
@@ -59,7 +89,7 @@ function parseCandidateFiles(context, tailwindConfig) {
59
89
  });
60
90
  // Normalize the file globs
61
91
  files = files.filter((filePath)=>typeof filePath === 'string');
62
- files = files.map(_normalizepath.default);
92
+ files = files.map(normalizePath);
63
93
  // Split into included and excluded globs
64
94
  let tasks = _fastglob.default.generateTasks(files);
65
95
  /** @type {ContentPath[]} */ let included = [];
@@ -86,6 +116,9 @@ function parseCandidateFiles(context, tailwindConfig) {
86
116
  * @param {boolean} ignore
87
117
  * @returns {ContentPath}
88
118
  */ function parseFilePath(filePath, ignore) {
119
+ // Escape special characters in the file path such as: ()[]
120
+ // But only if the special character isn't already escaped
121
+ filePath = filePath.replace(RegExp("(?<!\\\\)([\\[\\]\\(\\)])", "g"), '\\$1');
89
122
  let contentPath = {
90
123
  original: filePath,
91
124
  base: filePath,
@@ -107,7 +140,7 @@ function parseCandidateFiles(context, tailwindConfig) {
107
140
  // Afaik, this technically shouldn't be needed but there's probably
108
141
  // some internal, direct path matching with a normalized path in
109
142
  // a package which can't handle mixed directory separators
110
- let base = (0, _normalizepath.default)(contentPath.base);
143
+ let base = normalizePath(contentPath.base);
111
144
  // If the user's file path contains any special characters (like parens) for instance fast-glob
112
145
  // is like "OOOH SHINY" and treats them as such. So we have to escape the base path to fix this
113
146
  base = _fastglob.default.escapePath(base);
@@ -82,12 +82,21 @@ function* buildRegExps(context) {
82
82
  // Utilities
83
83
  _regex.pattern([
84
84
  // Utility Name / Group Name
85
- /-?(?:\w+)/,
85
+ _regex.any([
86
+ /-?(?:\w+)/,
87
+ // This is here to make sure @container supports everything that other utilities do
88
+ /@(?:\w+)/
89
+ ]),
86
90
  // Normal/Arbitrary values
87
91
  _regex.optional(_regex.any([
88
92
  _regex.pattern([
89
93
  // Arbitrary values
90
- /-(?:\w+-)*\[[^\s:]+\]/,
94
+ _regex.any([
95
+ /-(?:\w+-)*\['[^\s]+'\]/,
96
+ /-(?:\w+-)*\["[^\s]+"\]/,
97
+ /-(?:\w+-)*\[`[^\s]+`\]/,
98
+ /-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s:\[\]]+\]/
99
+ ]),
91
100
  // Not immediately followed by an `{[(`
92
101
  /(?![{([]])/,
93
102
  // optionally followed by an opacity modifier
@@ -95,7 +104,12 @@ function* buildRegExps(context) {
95
104
  ]),
96
105
  _regex.pattern([
97
106
  // Arbitrary values
98
- /-(?:\w+-)*\[[^\s]+\]/,
107
+ _regex.any([
108
+ /-(?:\w+-)*\['[^\s]+'\]/,
109
+ /-(?:\w+-)*\["[^\s]+"\]/,
110
+ /-(?:\w+-)*\[`[^\s]+`\]/,
111
+ /-(?:\w+-)*\[(?:[^\s\[\]]+\[[^\s\[\]]+\])*[^\s\[\]]+\]/
112
+ ]),
99
113
  // Not immediately followed by an `{[(`
100
114
  /(?![{([]])/,
101
115
  // optionally followed by an opacity modifier
@@ -285,6 +285,9 @@ function expandTailwindAtRules(context) {
285
285
  });
286
286
  root.append(cloned);
287
287
  }
288
+ var _root_source_end;
289
+ // TODO: Why is the root node having no source location for `end` possible?
290
+ root.source.end = (_root_source_end = root.source.end) !== null && _root_source_end !== void 0 ? _root_source_end : root.source.start;
288
291
  // If we've got a utility layer and no utilities are generated there's likely something wrong
289
292
  const hasUtilityVariants = variantNodes.some((node)=>{
290
293
  var _node_raws_tailwind;
@@ -163,6 +163,9 @@ function applyImportant(matches, classCandidate) {
163
163
  return matches;
164
164
  }
165
165
  let result = [];
166
+ function isInKeyframes(rule) {
167
+ return rule.parent && rule.parent.type === 'atrule' && rule.parent.name === 'keyframes';
168
+ }
166
169
  for (let [meta, rule] of matches){
167
170
  let container = _postcss.default.root({
168
171
  nodes: [
@@ -170,6 +173,11 @@ function applyImportant(matches, classCandidate) {
170
173
  ]
171
174
  });
172
175
  container.walkRules((r)=>{
176
+ // Declarations inside keyframes cannot be marked as important
177
+ // They will be ignored by the browser
178
+ if (isInKeyframes(r)) {
179
+ return;
180
+ }
173
181
  let ast = (0, _postcssselectorparser.default)().astSync(r.selector);
174
182
  // Remove extraneous selectors that do not include the base candidate
175
183
  ast.each((sel)=>(0, _formatVariantSelector.eliminateIrrelevantSelectors)(sel, classCandidate));
@@ -813,6 +821,10 @@ function applyFinalFormat(match, { context, candidate }) {
813
821
  if (!isValid) {
814
822
  return null;
815
823
  }
824
+ // If all rules have been eliminated we can skip this candidate entirely
825
+ if (container.nodes.length === 0) {
826
+ return null;
827
+ }
816
828
  match[1] = container.nodes[0];
817
829
  return match;
818
830
  }
@@ -2,10 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "loadConfig", {
6
- enumerable: true,
7
- get: function() {
5
+ function _export(target, all) {
6
+ for(var name in all)Object.defineProperty(target, name, {
7
+ enumerable: true,
8
+ get: all[name]
9
+ });
10
+ }
11
+ _export(exports, {
12
+ loadConfig: function() {
8
13
  return loadConfig;
14
+ },
15
+ useCustomJiti: function() {
16
+ return useCustomJiti;
9
17
  }
10
18
  });
11
19
  const _jiti = /*#__PURE__*/ _interop_require_default(require("jiti"));
@@ -16,6 +24,9 @@ function _interop_require_default(obj) {
16
24
  };
17
25
  }
18
26
  let jiti = null;
27
+ function useCustomJiti(_jiti) {
28
+ jiti = _jiti();
29
+ }
19
30
  function lazyJiti() {
20
31
  return jiti !== null && jiti !== void 0 ? jiti : jiti = (0, _jiti.default)(__filename, {
21
32
  interopDefault: true,
@@ -742,6 +742,7 @@ function resolvePlugins(context, root) {
742
742
  // TODO: This is a workaround for backwards compatibility, since custom variants
743
743
  // were historically sorted before screen/stackable variants.
744
744
  let beforeVariants = [
745
+ _corePlugins.variantPlugins['childVariant'],
745
746
  _corePlugins.variantPlugins['pseudoElementVariants'],
746
747
  _corePlugins.variantPlugins['pseudoClassVariants'],
747
748
  _corePlugins.variantPlugins['hasVariants'],
@@ -750,14 +751,31 @@ function resolvePlugins(context, root) {
750
751
  ];
751
752
  let afterVariants = [
752
753
  _corePlugins.variantPlugins['supportsVariants'],
753
- _corePlugins.variantPlugins['directionVariants'],
754
754
  _corePlugins.variantPlugins['reducedMotionVariants'],
755
755
  _corePlugins.variantPlugins['prefersContrastVariants'],
756
- _corePlugins.variantPlugins['darkVariants'],
757
- _corePlugins.variantPlugins['printVariant'],
758
756
  _corePlugins.variantPlugins['screenVariants'],
759
- _corePlugins.variantPlugins['orientationVariants']
757
+ _corePlugins.variantPlugins['orientationVariants'],
758
+ _corePlugins.variantPlugins['directionVariants'],
759
+ _corePlugins.variantPlugins['darkVariants'],
760
+ _corePlugins.variantPlugins['forcedColorsVariants'],
761
+ _corePlugins.variantPlugins['printVariant']
760
762
  ];
763
+ // This is a compatibility fix for the pre 3.4 dark mode behavior
764
+ // `class` retains the old behavior, but `selector` keeps the new behavior
765
+ let isLegacyDarkMode = context.tailwindConfig.darkMode === 'class' || Array.isArray(context.tailwindConfig.darkMode) && context.tailwindConfig.darkMode[0] === 'class';
766
+ if (isLegacyDarkMode) {
767
+ afterVariants = [
768
+ _corePlugins.variantPlugins['supportsVariants'],
769
+ _corePlugins.variantPlugins['reducedMotionVariants'],
770
+ _corePlugins.variantPlugins['prefersContrastVariants'],
771
+ _corePlugins.variantPlugins['darkVariants'],
772
+ _corePlugins.variantPlugins['screenVariants'],
773
+ _corePlugins.variantPlugins['orientationVariants'],
774
+ _corePlugins.variantPlugins['directionVariants'],
775
+ _corePlugins.variantPlugins['forcedColorsVariants'],
776
+ _corePlugins.variantPlugins['printVariant']
777
+ ];
778
+ }
761
779
  return [
762
780
  ...corePluginList,
763
781
  ...beforeVariants,
@@ -1,4 +1,9 @@
1
- "use strict";
1
+ /**
2
+ * @param {import('postcss').Container[]} nodes
3
+ * @param {any} source
4
+ * @param {any} raws
5
+ * @returns {import('postcss').Container[]}
6
+ */ "use strict";
2
7
  Object.defineProperty(exports, "__esModule", {
3
8
  value: true
4
9
  });
@@ -10,25 +15,40 @@ Object.defineProperty(exports, "default", {
10
15
  });
11
16
  function cloneNodes(nodes, source = undefined, raws = undefined) {
12
17
  return nodes.map((node)=>{
13
- var _node_raws_tailwind;
14
18
  let cloned = node.clone();
15
- // We always want override the source map
16
- // except when explicitly told not to
17
- let shouldOverwriteSource = ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.preserveSource) !== true || !cloned.source;
18
- if (source !== undefined && shouldOverwriteSource) {
19
- cloned.source = source;
20
- if ('walk' in cloned) {
21
- cloned.walk((child)=>{
22
- child.source = source;
23
- });
24
- }
25
- }
26
19
  if (raws !== undefined) {
27
20
  cloned.raws.tailwind = {
28
21
  ...cloned.raws.tailwind,
29
22
  ...raws
30
23
  };
31
24
  }
25
+ if (source !== undefined) {
26
+ traverse(cloned, (node)=>{
27
+ var _node_raws_tailwind;
28
+ // Do not traverse nodes that have opted
29
+ // to preserve their original source
30
+ let shouldPreserveSource = ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.preserveSource) === true && node.source;
31
+ if (shouldPreserveSource) {
32
+ return false;
33
+ }
34
+ // Otherwise we can safely replace the source
35
+ // And continue traversing
36
+ node.source = source;
37
+ });
38
+ }
32
39
  return cloned;
33
40
  });
34
41
  }
42
+ /**
43
+ * Traverse a tree of nodes and don't traverse children if the callback
44
+ * returns false. Ideally we'd use Container#walk instead of this
45
+ * function but it stops traversing siblings too.
46
+ *
47
+ * @param {import('postcss').Container} node
48
+ * @param {(node: import('postcss').Container) => boolean} onNode
49
+ */ function traverse(node, onNode) {
50
+ if (onNode(node) !== false) {
51
+ var _node_each;
52
+ (_node_each = node.each) === null || _node_each === void 0 ? void 0 : _node_each.call(node, (child)=>traverse(child, onNode));
53
+ }
54
+ }
@@ -115,7 +115,7 @@ function normalize(value, context = null, isRoot = true) {
115
115
  }
116
116
  /**
117
117
  * Add spaces around operators inside math functions
118
- * like calc() that do not follow an operator or '('.
118
+ * like calc() that do not follow an operator, '(', or `,`.
119
119
  *
120
120
  * @param {string} value
121
121
  * @returns {string}
@@ -141,7 +141,13 @@ function normalize(value, context = null, isRoot = true) {
141
141
  'keyboard-inset-bottom',
142
142
  'keyboard-inset-left',
143
143
  'keyboard-inset-width',
144
- 'keyboard-inset-height'
144
+ 'keyboard-inset-height',
145
+ 'radial-gradient',
146
+ 'linear-gradient',
147
+ 'conic-gradient',
148
+ 'repeating-radial-gradient',
149
+ 'repeating-linear-gradient',
150
+ 'repeating-conic-gradient'
145
151
  ];
146
152
  return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
147
153
  let result = '';
@@ -187,6 +193,10 @@ function normalize(value, context = null, isRoot = true) {
187
193
  result += consumeUntil([
188
194
  ')'
189
195
  ]);
196
+ } else if (peek('[')) {
197
+ result += consumeUntil([
198
+ ']'
199
+ ]);
190
200
  } else if ([
191
201
  '+',
192
202
  '-',
@@ -197,7 +207,8 @@ function normalize(value, context = null, isRoot = true) {
197
207
  '+',
198
208
  '-',
199
209
  '*',
200
- '/'
210
+ '/',
211
+ ','
201
212
  ].includes(lastChar())) {
202
213
  result += ` ${char} `;
203
214
  } else {
@@ -91,6 +91,19 @@ function isArbitraryValue(input) {
91
91
  }
92
92
  function splitUtilityModifier(modifier) {
93
93
  let slashIdx = modifier.lastIndexOf('/');
94
+ // If the `/` is inside an arbitrary, we want to find the previous one if any
95
+ // This logic probably isn't perfect but it should work for most cases
96
+ let arbitraryStartIdx = modifier.lastIndexOf('[', slashIdx);
97
+ let arbitraryEndIdx = modifier.indexOf(']', slashIdx);
98
+ let isNextToArbitrary = modifier[slashIdx - 1] === ']' || modifier[slashIdx + 1] === '[';
99
+ // Backtrack to the previous `/` if the one we found was inside an arbitrary
100
+ if (!isNextToArbitrary) {
101
+ if (arbitraryStartIdx !== -1 && arbitraryEndIdx !== -1) {
102
+ if (arbitraryStartIdx < slashIdx && slashIdx < arbitraryEndIdx) {
103
+ slashIdx = modifier.lastIndexOf('/', arbitraryStartIdx);
104
+ }
105
+ }
106
+ }
94
107
  if (slashIdx === -1 || slashIdx === modifier.length - 1) {
95
108
  return [
96
109
  modifier,
@@ -114,6 +114,9 @@ let elementProperties = {
114
114
  'terminal',
115
115
  'jumpable'
116
116
  ],
117
+ ':where': [],
118
+ ':is': [],
119
+ ':has': [],
117
120
  // The default value is used when the pseudo-element is not recognized
118
121
  // Because it's not recognized, we don't know if it's terminal or not
119
122
  // So we assume it can be moved AND can have user-action pseudo classes attached to it