tailwindcss 0.0.0-insiders.f667746 → 0.0.0-insiders.f69a46b
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.
- package/lib/corePlugins.js +46 -5
- package/lib/css/preflight.css +3 -3
- package/lib/lib/content.js +36 -3
- package/lib/lib/defaultExtractor.js +5 -1
- package/lib/lib/generateRules.js +9 -1
- package/lib/lib/load-config.js +1 -1
- package/lib/lib/offsets.js +51 -2
- package/lib/lib/resolveDefaultsAtRules.js +3 -1
- package/lib/lib/setupContextUtils.js +22 -5
- package/lib/util/dataTypes.js +11 -1
- package/lib/util/pseudoElements.js +3 -0
- package/package.json +12 -12
- package/src/corePlugins.js +47 -5
- package/src/css/preflight.css +3 -3
- package/src/lib/content.js +42 -1
- package/src/lib/defaultExtractor.js +6 -1
- package/src/lib/generateRules.js +11 -1
- package/src/lib/load-config.ts +2 -2
- package/src/lib/offsets.js +60 -1
- package/src/lib/resolveDefaultsAtRules.js +5 -1
- package/src/lib/setupContextUtils.js +26 -4
- package/src/util/dataTypes.js +12 -0
- package/src/util/pseudoElements.js +4 -0
- package/types/config.d.ts +7 -0
package/lib/corePlugins.js
CHANGED
|
@@ -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', '
|
|
269
|
-
addVariant('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,
|
|
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 === '
|
|
286
|
-
|
|
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 })=>{
|
package/lib/css/preflight.css
CHANGED
|
@@ -195,9 +195,9 @@ select {
|
|
|
195
195
|
*/
|
|
196
196
|
|
|
197
197
|
button,
|
|
198
|
-
[type='button'],
|
|
199
|
-
[type='reset'],
|
|
200
|
-
[type='submit'] {
|
|
198
|
+
input:where([type='button']),
|
|
199
|
+
input:where([type='reset']),
|
|
200
|
+
input:where([type='submit']) {
|
|
201
201
|
-webkit-appearance: button; /* 1 */
|
|
202
202
|
background-color: transparent; /* 2 */
|
|
203
203
|
background-image: none; /* 2 */
|
package/lib/lib/content.js
CHANGED
|
@@ -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(
|
|
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 = (
|
|
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,7 +82,11 @@ function* buildRegExps(context) {
|
|
|
82
82
|
// Utilities
|
|
83
83
|
_regex.pattern([
|
|
84
84
|
// Utility Name / Group Name
|
|
85
|
-
|
|
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([
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -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));
|
|
@@ -504,7 +512,7 @@ function extractArbitraryProperty(classCandidate, context) {
|
|
|
504
512
|
if (!isParsableCssValue(property, normalized)) {
|
|
505
513
|
return null;
|
|
506
514
|
}
|
|
507
|
-
let sort = context.offsets.arbitraryProperty();
|
|
515
|
+
let sort = context.offsets.arbitraryProperty(classCandidate);
|
|
508
516
|
return [
|
|
509
517
|
[
|
|
510
518
|
{
|
package/lib/lib/load-config.js
CHANGED
package/lib/lib/offsets.js
CHANGED
|
@@ -28,15 +28,19 @@ class Offsets {
|
|
|
28
28
|
variants: 0n,
|
|
29
29
|
parallelIndex: 0n,
|
|
30
30
|
index: this.offsets[layer]++,
|
|
31
|
+
propertyOffset: 0n,
|
|
32
|
+
property: '',
|
|
31
33
|
options: []
|
|
32
34
|
};
|
|
33
35
|
}
|
|
34
36
|
/**
|
|
37
|
+
* @param {string} name
|
|
35
38
|
* @returns {RuleOffset}
|
|
36
|
-
*/ arbitraryProperty() {
|
|
39
|
+
*/ arbitraryProperty(name) {
|
|
37
40
|
return {
|
|
38
41
|
...this.create('utilities'),
|
|
39
|
-
arbitrary: 1n
|
|
42
|
+
arbitrary: 1n,
|
|
43
|
+
property: name
|
|
40
44
|
};
|
|
41
45
|
}
|
|
42
46
|
/**
|
|
@@ -176,6 +180,10 @@ class Offsets {
|
|
|
176
180
|
if (a.arbitrary !== b.arbitrary) {
|
|
177
181
|
return a.arbitrary - b.arbitrary;
|
|
178
182
|
}
|
|
183
|
+
// Always sort arbitrary properties alphabetically
|
|
184
|
+
if (a.propertyOffset !== b.propertyOffset) {
|
|
185
|
+
return a.propertyOffset - b.propertyOffset;
|
|
186
|
+
}
|
|
179
187
|
// Sort utilities, components, etc… in the order they were registered
|
|
180
188
|
return a.index - b.index;
|
|
181
189
|
}
|
|
@@ -229,8 +237,49 @@ class Offsets {
|
|
|
229
237
|
* @template T
|
|
230
238
|
* @param {[RuleOffset, T][]} list
|
|
231
239
|
* @returns {[RuleOffset, T][]}
|
|
240
|
+
*/ sortArbitraryProperties(list) {
|
|
241
|
+
// Collect all known arbitrary properties
|
|
242
|
+
let known = new Set();
|
|
243
|
+
for (let [offset] of list){
|
|
244
|
+
if (offset.arbitrary === 1n) {
|
|
245
|
+
known.add(offset.property);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// No arbitrary properties? Nothing to do.
|
|
249
|
+
if (known.size === 0) {
|
|
250
|
+
return list;
|
|
251
|
+
}
|
|
252
|
+
// Sort the properties alphabetically
|
|
253
|
+
let properties = Array.from(known).sort();
|
|
254
|
+
// Create a map from the property name to its offset
|
|
255
|
+
let offsets = new Map();
|
|
256
|
+
let offset = 1n;
|
|
257
|
+
for (let property of properties){
|
|
258
|
+
offsets.set(property, offset++);
|
|
259
|
+
}
|
|
260
|
+
// Apply the sorted offsets to the list
|
|
261
|
+
return list.map((item)=>{
|
|
262
|
+
let [offset, rule] = item;
|
|
263
|
+
var _offsets_get;
|
|
264
|
+
offset = {
|
|
265
|
+
...offset,
|
|
266
|
+
propertyOffset: (_offsets_get = offsets.get(offset.property)) !== null && _offsets_get !== void 0 ? _offsets_get : 0n
|
|
267
|
+
};
|
|
268
|
+
return [
|
|
269
|
+
offset,
|
|
270
|
+
rule
|
|
271
|
+
];
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* @template T
|
|
276
|
+
* @param {[RuleOffset, T][]} list
|
|
277
|
+
* @returns {[RuleOffset, T][]}
|
|
232
278
|
*/ sort(list) {
|
|
279
|
+
// Sort arbitrary variants so they're in alphabetical order
|
|
233
280
|
list = this.remapArbitraryVariantOffsets(list);
|
|
281
|
+
// Sort arbitrary properties so they're in alphabetical order
|
|
282
|
+
list = this.sortArbitraryProperties(list);
|
|
234
283
|
return list.sort(([a], [b])=>(0, _bigSign.default)(this.compare(a, b)));
|
|
235
284
|
}
|
|
236
285
|
constructor(){
|
|
@@ -111,7 +111,9 @@ function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
111
111
|
// we consider them separately because merging the declarations into
|
|
112
112
|
// a single rule will cause browsers that do not understand the
|
|
113
113
|
// vendor prefix to throw out the whole rule
|
|
114
|
-
|
|
114
|
+
// Additionally if a selector contains `:has` we also consider
|
|
115
|
+
// it separately because FF only recently gained support for it
|
|
116
|
+
let selectorGroupName = selector.includes(':-') || selector.includes('::-') || selector.includes(':has') ? selector : '__DEFAULT__';
|
|
115
117
|
var _selectorGroups_get;
|
|
116
118
|
let selectors = (_selectorGroups_get = selectorGroups.get(selectorGroupName)) !== null && _selectorGroups_get !== void 0 ? _selectorGroups_get : new Set();
|
|
117
119
|
selectorGroups.set(selectorGroupName, selectors);
|
|
@@ -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,15 +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['forcedColorsVariants'],
|
|
757
|
-
_corePlugins.variantPlugins['darkVariants'],
|
|
758
|
-
_corePlugins.variantPlugins['printVariant'],
|
|
759
756
|
_corePlugins.variantPlugins['screenVariants'],
|
|
760
|
-
_corePlugins.variantPlugins['orientationVariants']
|
|
757
|
+
_corePlugins.variantPlugins['orientationVariants'],
|
|
758
|
+
_corePlugins.variantPlugins['directionVariants'],
|
|
759
|
+
_corePlugins.variantPlugins['darkVariants'],
|
|
760
|
+
_corePlugins.variantPlugins['forcedColorsVariants'],
|
|
761
|
+
_corePlugins.variantPlugins['printVariant']
|
|
761
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
|
+
}
|
|
762
779
|
return [
|
|
763
780
|
...corePluginList,
|
|
764
781
|
...beforeVariants,
|
package/lib/util/dataTypes.js
CHANGED
|
@@ -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
|
'-',
|
|
@@ -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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tailwindcss",
|
|
3
|
-
"version": "0.0.0-insiders.
|
|
3
|
+
"version": "0.0.0-insiders.f69a46b",
|
|
4
4
|
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -44,47 +44,47 @@
|
|
|
44
44
|
],
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@swc/cli": "^0.1.63",
|
|
47
|
-
"@swc/core": "^1.3.
|
|
47
|
+
"@swc/core": "^1.3.101",
|
|
48
48
|
"@swc/jest": "^0.2.29",
|
|
49
49
|
"@swc/register": "^0.1.10",
|
|
50
50
|
"concurrently": "^8.0.1",
|
|
51
|
-
"eslint": "^8.
|
|
52
|
-
"eslint-config-prettier": "^9.
|
|
51
|
+
"eslint": "^8.56.0",
|
|
52
|
+
"eslint-config-prettier": "^9.1.0",
|
|
53
53
|
"eslint-plugin-prettier": "^4.2.1",
|
|
54
54
|
"jest": "^29.7.0",
|
|
55
55
|
"jest-diff": "^29.7.0",
|
|
56
56
|
"prettier": "^2.8.8",
|
|
57
57
|
"rimraf": "^5.0.0",
|
|
58
58
|
"source-map-js": "^1.0.2",
|
|
59
|
-
"turbo": "^1.
|
|
59
|
+
"turbo": "^1.12.3"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@alloc/quick-lru": "^5.2.0",
|
|
63
|
-
"@tailwindcss/oxide": "0.0.0-insiders.
|
|
63
|
+
"@tailwindcss/oxide": "0.0.0-insiders.f69a46b",
|
|
64
64
|
"arg": "^5.0.2",
|
|
65
|
-
"browserslist": "^4.22.
|
|
66
|
-
"chokidar": "^3.
|
|
65
|
+
"browserslist": "^4.22.3",
|
|
66
|
+
"chokidar": "^3.6.0",
|
|
67
67
|
"didyoumean": "^1.2.2",
|
|
68
68
|
"dlv": "^1.1.3",
|
|
69
69
|
"fast-glob": "^3.3.2",
|
|
70
70
|
"glob-parent": "^6.0.2",
|
|
71
71
|
"is-glob": "^4.0.3",
|
|
72
72
|
"jiti": "^1.21.0",
|
|
73
|
-
"lightningcss": "^1.
|
|
73
|
+
"lightningcss": "^1.23.0",
|
|
74
74
|
"lilconfig": "^3.0.0",
|
|
75
75
|
"micromatch": "^4.0.5",
|
|
76
76
|
"normalize-path": "^3.0.0",
|
|
77
77
|
"object-hash": "^3.0.0",
|
|
78
78
|
"picocolors": "^1.0.0",
|
|
79
|
-
"postcss": "^8.4.
|
|
79
|
+
"postcss": "^8.4.35",
|
|
80
80
|
"postcss-import": "^15.1.0",
|
|
81
81
|
"postcss-js": "^4.0.1",
|
|
82
82
|
"postcss-load-config": "^4.0.2",
|
|
83
83
|
"postcss-nested": "^6.0.1",
|
|
84
|
-
"postcss-selector-parser": "^6.0.
|
|
84
|
+
"postcss-selector-parser": "^6.0.15",
|
|
85
85
|
"postcss-value-parser": "^4.2.0",
|
|
86
86
|
"resolve": "^1.22.8",
|
|
87
|
-
"sucrase": "^3.
|
|
87
|
+
"sucrase": "^3.35.0"
|
|
88
88
|
},
|
|
89
89
|
"browserslist": [
|
|
90
90
|
"defaults and supports css-variables and supports css-matches-pseudo",
|
package/src/corePlugins.js
CHANGED
|
@@ -24,6 +24,9 @@ import { normalize } from './util/dataTypes'
|
|
|
24
24
|
import { INTERNAL_FEATURES } from './lib/setupContextUtils'
|
|
25
25
|
|
|
26
26
|
export let variantPlugins = {
|
|
27
|
+
childVariant: ({ addVariant }) => {
|
|
28
|
+
addVariant('*', '& > *')
|
|
29
|
+
},
|
|
27
30
|
pseudoElementVariants: ({ addVariant }) => {
|
|
28
31
|
addVariant('first-letter', '&::first-letter')
|
|
29
32
|
addVariant('first-line', '&::first-line')
|
|
@@ -203,8 +206,8 @@ export let variantPlugins = {
|
|
|
203
206
|
},
|
|
204
207
|
|
|
205
208
|
directionVariants: ({ addVariant }) => {
|
|
206
|
-
addVariant('ltr', '
|
|
207
|
-
addVariant('rtl', '
|
|
209
|
+
addVariant('ltr', '&:where([dir="ltr"], [dir="ltr"] *)')
|
|
210
|
+
addVariant('rtl', '&:where([dir="rtl"], [dir="rtl"] *)')
|
|
208
211
|
},
|
|
209
212
|
|
|
210
213
|
reducedMotionVariants: ({ addVariant }) => {
|
|
@@ -213,7 +216,7 @@ export let variantPlugins = {
|
|
|
213
216
|
},
|
|
214
217
|
|
|
215
218
|
darkVariants: ({ config, addVariant }) => {
|
|
216
|
-
let [mode,
|
|
219
|
+
let [mode, selector = '.dark'] = [].concat(config('darkMode', 'media'))
|
|
217
220
|
|
|
218
221
|
if (mode === false) {
|
|
219
222
|
mode = 'media'
|
|
@@ -224,10 +227,49 @@ export let variantPlugins = {
|
|
|
224
227
|
])
|
|
225
228
|
}
|
|
226
229
|
|
|
227
|
-
if (mode === '
|
|
228
|
-
|
|
230
|
+
if (mode === 'variant') {
|
|
231
|
+
let formats
|
|
232
|
+
if (Array.isArray(selector)) {
|
|
233
|
+
formats = selector
|
|
234
|
+
} else if (typeof selector === 'function') {
|
|
235
|
+
formats = selector
|
|
236
|
+
} else if (typeof selector === 'string') {
|
|
237
|
+
formats = [selector]
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// TODO: We could also add these warnings if the user passes a function that returns string | string[]
|
|
241
|
+
// But this is an advanced enough use case that it's probably not necessary
|
|
242
|
+
if (Array.isArray(formats)) {
|
|
243
|
+
for (let format of formats) {
|
|
244
|
+
if (format === '.dark') {
|
|
245
|
+
mode = false
|
|
246
|
+
log.warn('darkmode-variant-without-selector', [
|
|
247
|
+
'When using `variant` for `darkMode`, you must provide a selector.',
|
|
248
|
+
'Example: `darkMode: ["variant", ".your-selector &"]`',
|
|
249
|
+
])
|
|
250
|
+
} else if (!format.includes('&')) {
|
|
251
|
+
mode = false
|
|
252
|
+
log.warn('darkmode-variant-without-ampersand', [
|
|
253
|
+
'When using `variant` for `darkMode`, your selector must contain `&`.',
|
|
254
|
+
'Example `darkMode: ["variant", ".your-selector &"]`',
|
|
255
|
+
])
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
selector = formats
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (mode === 'selector') {
|
|
264
|
+
// New preferred behavior
|
|
265
|
+
addVariant('dark', `&:where(${selector}, ${selector} *)`)
|
|
229
266
|
} else if (mode === 'media') {
|
|
230
267
|
addVariant('dark', '@media (prefers-color-scheme: dark)')
|
|
268
|
+
} else if (mode === 'variant') {
|
|
269
|
+
addVariant('dark', selector)
|
|
270
|
+
} else if (mode === 'class') {
|
|
271
|
+
// Old behavior
|
|
272
|
+
addVariant('dark', `:is(${selector} &)`)
|
|
231
273
|
}
|
|
232
274
|
},
|
|
233
275
|
|
package/src/css/preflight.css
CHANGED
|
@@ -195,9 +195,9 @@ select {
|
|
|
195
195
|
*/
|
|
196
196
|
|
|
197
197
|
button,
|
|
198
|
-
[type='button'],
|
|
199
|
-
[type='reset'],
|
|
200
|
-
[type='submit'] {
|
|
198
|
+
input:where([type='button']),
|
|
199
|
+
input:where([type='reset']),
|
|
200
|
+
input:where([type='submit']) {
|
|
201
201
|
-webkit-appearance: button; /* 1 */
|
|
202
202
|
background-color: transparent; /* 2 */
|
|
203
203
|
background-image: none; /* 2 */
|
package/src/lib/content.js
CHANGED
|
@@ -4,11 +4,48 @@ import fs from 'fs'
|
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import isGlob from 'is-glob'
|
|
6
6
|
import fastGlob from 'fast-glob'
|
|
7
|
-
import normalizePath from 'normalize-path'
|
|
8
7
|
import { parseGlob } from '../util/parseGlob'
|
|
9
8
|
import { env } from './sharedState'
|
|
10
9
|
import { resolveContentPaths } from '@tailwindcss/oxide'
|
|
11
10
|
|
|
11
|
+
/*!
|
|
12
|
+
* Modified version of normalize-path, original license below
|
|
13
|
+
*
|
|
14
|
+
* normalize-path <https://github.com/jonschlinkert/normalize-path>
|
|
15
|
+
*
|
|
16
|
+
* Copyright (c) 2014-2018, Jon Schlinkert.
|
|
17
|
+
* Released under the MIT License.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
function normalizePath(path) {
|
|
21
|
+
if (typeof path !== 'string') {
|
|
22
|
+
throw new TypeError('expected path to be a string')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (path === '\\' || path === '/') return '/'
|
|
26
|
+
|
|
27
|
+
var len = path.length
|
|
28
|
+
if (len <= 1) return path
|
|
29
|
+
|
|
30
|
+
// ensure that win32 namespaces has two leading slashes, so that the path is
|
|
31
|
+
// handled properly by the win32 version of path.parse() after being normalized
|
|
32
|
+
// https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces
|
|
33
|
+
var prefix = ''
|
|
34
|
+
if (len > 4 && path[3] === '\\') {
|
|
35
|
+
var ch = path[2]
|
|
36
|
+
if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') {
|
|
37
|
+
path = path.slice(2)
|
|
38
|
+
prefix = '//'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Modified part: instead of purely splitting on `\\` and `/`, we split on
|
|
43
|
+
// `/` and `\\` that is _not_ followed by any of the following characters: ()[]
|
|
44
|
+
// This is to ensure that we keep the escaping of brackets and parentheses
|
|
45
|
+
let segs = path.split(/[/\\]+(?![\(\)\[\]])/)
|
|
46
|
+
return prefix + segs.join('/')
|
|
47
|
+
}
|
|
48
|
+
|
|
12
49
|
/** @typedef {import('../../types/config.js').RawFile} RawFile */
|
|
13
50
|
/** @typedef {import('../../types/config.js').FilePath} FilePath */
|
|
14
51
|
|
|
@@ -105,6 +142,10 @@ export function parseCandidateFiles(context, tailwindConfig) {
|
|
|
105
142
|
* @returns {ContentPath}
|
|
106
143
|
*/
|
|
107
144
|
function parseFilePath(filePath, ignore) {
|
|
145
|
+
// Escape special characters in the file path such as: ()[]
|
|
146
|
+
// But only if the special character isn't already escaped
|
|
147
|
+
filePath = filePath.replace(/(?<!\\)([\[\]\(\)])/g, '\\$1')
|
|
148
|
+
|
|
108
149
|
let contentPath = {
|
|
109
150
|
original: filePath,
|
|
110
151
|
base: filePath,
|
|
@@ -40,7 +40,12 @@ function* buildRegExps(context) {
|
|
|
40
40
|
// Utilities
|
|
41
41
|
regex.pattern([
|
|
42
42
|
// Utility Name / Group Name
|
|
43
|
-
|
|
43
|
+
regex.any([
|
|
44
|
+
/-?(?:\w+)/,
|
|
45
|
+
|
|
46
|
+
// This is here to make sure @container supports everything that other utilities do
|
|
47
|
+
/@(?:\w+)/,
|
|
48
|
+
]),
|
|
44
49
|
|
|
45
50
|
// Normal/Arbitrary values
|
|
46
51
|
regex.optional(
|
package/src/lib/generateRules.js
CHANGED
|
@@ -118,10 +118,20 @@ function applyImportant(matches, classCandidate) {
|
|
|
118
118
|
|
|
119
119
|
let result = []
|
|
120
120
|
|
|
121
|
+
function isInKeyframes(rule) {
|
|
122
|
+
return rule.parent && rule.parent.type === 'atrule' && rule.parent.name === 'keyframes'
|
|
123
|
+
}
|
|
124
|
+
|
|
121
125
|
for (let [meta, rule] of matches) {
|
|
122
126
|
let container = postcss.root({ nodes: [rule.clone()] })
|
|
123
127
|
|
|
124
128
|
container.walkRules((r) => {
|
|
129
|
+
// Declarations inside keyframes cannot be marked as important
|
|
130
|
+
// They will be ignored by the browser
|
|
131
|
+
if (isInKeyframes(r)) {
|
|
132
|
+
return
|
|
133
|
+
}
|
|
134
|
+
|
|
125
135
|
let ast = selectorParser().astSync(r.selector)
|
|
126
136
|
|
|
127
137
|
// Remove extraneous selectors that do not include the base candidate
|
|
@@ -497,7 +507,7 @@ function extractArbitraryProperty(classCandidate, context) {
|
|
|
497
507
|
return null
|
|
498
508
|
}
|
|
499
509
|
|
|
500
|
-
let sort = context.offsets.arbitraryProperty()
|
|
510
|
+
let sort = context.offsets.arbitraryProperty(classCandidate)
|
|
501
511
|
|
|
502
512
|
return [
|
|
503
513
|
[
|
package/src/lib/load-config.ts
CHANGED
|
@@ -8,8 +8,8 @@ let jiti: ReturnType<typeof jitiFactory> | null = null
|
|
|
8
8
|
// @internal
|
|
9
9
|
// This WILL be removed in some future release
|
|
10
10
|
// If you rely on this your stuff WILL break
|
|
11
|
-
export function useCustomJiti(_jiti: ReturnType<typeof jitiFactory>) {
|
|
12
|
-
jiti = _jiti
|
|
11
|
+
export function useCustomJiti(_jiti: () => ReturnType<typeof jitiFactory>) {
|
|
12
|
+
jiti = _jiti()
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
function lazyJiti() {
|
package/src/lib/offsets.js
CHANGED
|
@@ -24,6 +24,8 @@ import { remapBitfield } from './remap-bitfield.js'
|
|
|
24
24
|
* @property {bigint} variants Dynamic size. 1 bit per registered variant. 0n means no variants
|
|
25
25
|
* @property {bigint} parallelIndex Rule index for the parallel variant. 0 if not applicable.
|
|
26
26
|
* @property {bigint} index Index of the rule / utility in its given *parent* layer. Monotonically increasing.
|
|
27
|
+
* @property {bigint} propertyOffset Offset for the arbitrary property. Only valid after sorting.
|
|
28
|
+
* @property {string} property Name/Value of the arbitrary property.
|
|
27
29
|
* @property {VariantOption[]} options Some information on how we can sort arbitrary variants
|
|
28
30
|
*/
|
|
29
31
|
|
|
@@ -88,17 +90,21 @@ export class Offsets {
|
|
|
88
90
|
variants: 0n,
|
|
89
91
|
parallelIndex: 0n,
|
|
90
92
|
index: this.offsets[layer]++,
|
|
93
|
+
propertyOffset: 0n,
|
|
94
|
+
property: '',
|
|
91
95
|
options: [],
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
/**
|
|
100
|
+
* @param {string} name
|
|
96
101
|
* @returns {RuleOffset}
|
|
97
102
|
*/
|
|
98
|
-
arbitraryProperty() {
|
|
103
|
+
arbitraryProperty(name) {
|
|
99
104
|
return {
|
|
100
105
|
...this.create('utilities'),
|
|
101
106
|
arbitrary: 1n,
|
|
107
|
+
property: name,
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
|
|
@@ -262,6 +268,11 @@ export class Offsets {
|
|
|
262
268
|
return a.arbitrary - b.arbitrary
|
|
263
269
|
}
|
|
264
270
|
|
|
271
|
+
// Always sort arbitrary properties alphabetically
|
|
272
|
+
if (a.propertyOffset !== b.propertyOffset) {
|
|
273
|
+
return a.propertyOffset - b.propertyOffset
|
|
274
|
+
}
|
|
275
|
+
|
|
265
276
|
// Sort utilities, components, etc… in the order they were registered
|
|
266
277
|
return a.index - b.index
|
|
267
278
|
}
|
|
@@ -320,14 +331,62 @@ export class Offsets {
|
|
|
320
331
|
})
|
|
321
332
|
}
|
|
322
333
|
|
|
334
|
+
/**
|
|
335
|
+
* @template T
|
|
336
|
+
* @param {[RuleOffset, T][]} list
|
|
337
|
+
* @returns {[RuleOffset, T][]}
|
|
338
|
+
*/
|
|
339
|
+
sortArbitraryProperties(list) {
|
|
340
|
+
// Collect all known arbitrary properties
|
|
341
|
+
let known = new Set()
|
|
342
|
+
|
|
343
|
+
for (let [offset] of list) {
|
|
344
|
+
if (offset.arbitrary === 1n) {
|
|
345
|
+
known.add(offset.property)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// No arbitrary properties? Nothing to do.
|
|
350
|
+
if (known.size === 0) {
|
|
351
|
+
return list
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Sort the properties alphabetically
|
|
355
|
+
let properties = Array.from(known).sort()
|
|
356
|
+
|
|
357
|
+
// Create a map from the property name to its offset
|
|
358
|
+
let offsets = new Map()
|
|
359
|
+
|
|
360
|
+
let offset = 1n
|
|
361
|
+
for (let property of properties) {
|
|
362
|
+
offsets.set(property, offset++)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Apply the sorted offsets to the list
|
|
366
|
+
return list.map((item) => {
|
|
367
|
+
let [offset, rule] = item
|
|
368
|
+
|
|
369
|
+
offset = {
|
|
370
|
+
...offset,
|
|
371
|
+
propertyOffset: offsets.get(offset.property) ?? 0n,
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return [offset, rule]
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
|
|
323
378
|
/**
|
|
324
379
|
* @template T
|
|
325
380
|
* @param {[RuleOffset, T][]} list
|
|
326
381
|
* @returns {[RuleOffset, T][]}
|
|
327
382
|
*/
|
|
328
383
|
sort(list) {
|
|
384
|
+
// Sort arbitrary variants so they're in alphabetical order
|
|
329
385
|
list = this.remapArbitraryVariantOffsets(list)
|
|
330
386
|
|
|
387
|
+
// Sort arbitrary properties so they're in alphabetical order
|
|
388
|
+
list = this.sortArbitraryProperties(list)
|
|
389
|
+
|
|
331
390
|
return list.sort(([a], [b]) => bigSign(this.compare(a, b)))
|
|
332
391
|
}
|
|
333
392
|
}
|
|
@@ -104,8 +104,12 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
104
104
|
// we consider them separately because merging the declarations into
|
|
105
105
|
// a single rule will cause browsers that do not understand the
|
|
106
106
|
// vendor prefix to throw out the whole rule
|
|
107
|
+
// Additionally if a selector contains `:has` we also consider
|
|
108
|
+
// it separately because FF only recently gained support for it
|
|
107
109
|
let selectorGroupName =
|
|
108
|
-
selector.includes(':-') || selector.includes('::-')
|
|
110
|
+
selector.includes(':-') || selector.includes('::-') || selector.includes(':has')
|
|
111
|
+
? selector
|
|
112
|
+
: '__DEFAULT__'
|
|
109
113
|
|
|
110
114
|
let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
|
|
111
115
|
selectorGroups.set(selectorGroupName, selectors)
|
|
@@ -746,6 +746,7 @@ function resolvePlugins(context, root) {
|
|
|
746
746
|
// TODO: This is a workaround for backwards compatibility, since custom variants
|
|
747
747
|
// were historically sorted before screen/stackable variants.
|
|
748
748
|
let beforeVariants = [
|
|
749
|
+
variantPlugins['childVariant'],
|
|
749
750
|
variantPlugins['pseudoElementVariants'],
|
|
750
751
|
variantPlugins['pseudoClassVariants'],
|
|
751
752
|
variantPlugins['hasVariants'],
|
|
@@ -754,16 +755,37 @@ function resolvePlugins(context, root) {
|
|
|
754
755
|
]
|
|
755
756
|
let afterVariants = [
|
|
756
757
|
variantPlugins['supportsVariants'],
|
|
757
|
-
variantPlugins['directionVariants'],
|
|
758
758
|
variantPlugins['reducedMotionVariants'],
|
|
759
759
|
variantPlugins['prefersContrastVariants'],
|
|
760
|
-
variantPlugins['forcedColorsVariants'],
|
|
761
|
-
variantPlugins['darkVariants'],
|
|
762
|
-
variantPlugins['printVariant'],
|
|
763
760
|
variantPlugins['screenVariants'],
|
|
764
761
|
variantPlugins['orientationVariants'],
|
|
762
|
+
variantPlugins['directionVariants'],
|
|
763
|
+
variantPlugins['darkVariants'],
|
|
764
|
+
variantPlugins['forcedColorsVariants'],
|
|
765
|
+
variantPlugins['printVariant'],
|
|
765
766
|
]
|
|
766
767
|
|
|
768
|
+
// This is a compatibility fix for the pre 3.4 dark mode behavior
|
|
769
|
+
// `class` retains the old behavior, but `selector` keeps the new behavior
|
|
770
|
+
let isLegacyDarkMode =
|
|
771
|
+
context.tailwindConfig.darkMode === 'class' ||
|
|
772
|
+
(Array.isArray(context.tailwindConfig.darkMode) &&
|
|
773
|
+
context.tailwindConfig.darkMode[0] === 'class')
|
|
774
|
+
|
|
775
|
+
if (isLegacyDarkMode) {
|
|
776
|
+
afterVariants = [
|
|
777
|
+
variantPlugins['supportsVariants'],
|
|
778
|
+
variantPlugins['reducedMotionVariants'],
|
|
779
|
+
variantPlugins['prefersContrastVariants'],
|
|
780
|
+
variantPlugins['darkVariants'],
|
|
781
|
+
variantPlugins['screenVariants'],
|
|
782
|
+
variantPlugins['orientationVariants'],
|
|
783
|
+
variantPlugins['directionVariants'],
|
|
784
|
+
variantPlugins['forcedColorsVariants'],
|
|
785
|
+
variantPlugins['printVariant'],
|
|
786
|
+
]
|
|
787
|
+
}
|
|
788
|
+
|
|
767
789
|
return [...corePluginList, ...beforeVariants, ...userPlugins, ...afterVariants, ...layerPlugins]
|
|
768
790
|
}
|
|
769
791
|
|
package/src/util/dataTypes.js
CHANGED
|
@@ -107,6 +107,13 @@ function normalizeMathOperatorSpacing(value) {
|
|
|
107
107
|
'keyboard-inset-left',
|
|
108
108
|
'keyboard-inset-width',
|
|
109
109
|
'keyboard-inset-height',
|
|
110
|
+
|
|
111
|
+
'radial-gradient',
|
|
112
|
+
'linear-gradient',
|
|
113
|
+
'conic-gradient',
|
|
114
|
+
'repeating-radial-gradient',
|
|
115
|
+
'repeating-linear-gradient',
|
|
116
|
+
'repeating-conic-gradient',
|
|
110
117
|
]
|
|
111
118
|
|
|
112
119
|
return value.replace(/(calc|min|max|clamp)\(.+\)/g, (match) => {
|
|
@@ -162,6 +169,11 @@ function normalizeMathOperatorSpacing(value) {
|
|
|
162
169
|
result += consumeUntil([')'])
|
|
163
170
|
}
|
|
164
171
|
|
|
172
|
+
// Don't break CSS grid track names
|
|
173
|
+
else if (peek('[')) {
|
|
174
|
+
result += consumeUntil([']'])
|
|
175
|
+
}
|
|
176
|
+
|
|
165
177
|
// Handle operators
|
|
166
178
|
else if (
|
|
167
179
|
['+', '-', '*', '/'].includes(char) &&
|
|
@@ -60,6 +60,10 @@ let elementProperties = {
|
|
|
60
60
|
':first-letter': ['terminal', 'jumpable'],
|
|
61
61
|
':first-line': ['terminal', 'jumpable'],
|
|
62
62
|
|
|
63
|
+
':where': [],
|
|
64
|
+
':is': [],
|
|
65
|
+
':has': [],
|
|
66
|
+
|
|
63
67
|
// The default value is used when the pseudo-element is not recognized
|
|
64
68
|
// Because it's not recognized, we don't know if it's terminal or not
|
|
65
69
|
// So we assume it can be moved AND can have user-action pseudo classes attached to it
|
package/types/config.d.ts
CHANGED
|
@@ -75,6 +75,13 @@ type DarkModeConfig =
|
|
|
75
75
|
| 'class'
|
|
76
76
|
// Use the `class` strategy with a custom class instead of `.dark`.
|
|
77
77
|
| ['class', string]
|
|
78
|
+
// Use the `selector` strategy — same as `class` but uses `:where()` for more predicable behavior
|
|
79
|
+
| 'selector'
|
|
80
|
+
// Use the `selector` strategy with a custom selector instead of `.dark`.
|
|
81
|
+
| ['selector', string]
|
|
82
|
+
// Use the `variant` strategy, which allows you to completely customize the selector
|
|
83
|
+
// It takes a string or an array of strings, which are passed directly to `addVariant()`
|
|
84
|
+
| ['variant', string | string[]]
|
|
78
85
|
|
|
79
86
|
type Screen = { raw: string } | { min: string } | { max: string } | { min: string; max: string }
|
|
80
87
|
type ScreensConfig = string[] | KeyValuePair<string, string | Screen | Screen[]>
|