tailwindcss 3.2.4 → 3.2.5
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/CHANGELOG.md +44 -1
- package/README.md +1 -1
- package/lib/cli/build/index.js +5 -1
- package/lib/cli/build/plugin.js +39 -34
- package/lib/cli/index.js +231 -10
- package/lib/cli/init/index.js +2 -2
- package/lib/cli.js +4 -226
- package/lib/corePlugins.js +45 -27
- package/lib/featureFlags.js +8 -8
- package/lib/index.js +4 -46
- package/lib/lib/collapseAdjacentRules.js +2 -2
- package/lib/lib/collapseDuplicateDeclarations.js +2 -2
- package/lib/lib/content.js +16 -16
- package/lib/lib/defaultExtractor.js +10 -5
- package/lib/lib/detectNesting.js +7 -1
- package/lib/lib/evaluateTailwindFunctions.js +4 -4
- package/lib/lib/expandApplyAtRules.js +2 -2
- package/lib/lib/expandTailwindAtRules.js +35 -9
- package/lib/lib/findAtConfigPath.js +3 -3
- package/lib/lib/generateRules.js +105 -50
- package/lib/lib/offsets.js +88 -1
- package/lib/lib/remap-bitfield.js +87 -0
- package/lib/lib/resolveDefaultsAtRules.js +4 -4
- package/lib/lib/setupContextUtils.js +121 -80
- package/lib/lib/setupTrackingContext.js +25 -4
- package/lib/lib/sharedState.js +19 -1
- package/lib/oxide/cli/build/deps.js +81 -0
- package/lib/oxide/cli/build/index.js +47 -0
- package/lib/oxide/cli/build/plugin.js +364 -0
- package/lib/oxide/cli/build/utils.js +77 -0
- package/lib/oxide/cli/build/watching.js +177 -0
- package/lib/oxide/cli/help/index.js +70 -0
- package/lib/oxide/cli/index.js +220 -0
- package/lib/oxide/cli/init/index.js +35 -0
- package/lib/oxide/cli.js +5 -0
- package/lib/oxide/postcss-plugin.js +2 -0
- package/lib/plugin.js +98 -0
- package/lib/postcss-plugins/nesting/plugin.js +2 -2
- package/lib/util/cloneNodes.js +2 -2
- package/lib/util/color.js +20 -6
- package/lib/util/createUtilityPlugin.js +2 -2
- package/lib/util/dataTypes.js +26 -2
- package/lib/util/defaults.js +4 -4
- package/lib/util/escapeClassName.js +3 -3
- package/lib/util/formatVariantSelector.js +171 -105
- package/lib/util/getAllConfigs.js +2 -2
- package/lib/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +2 -2
- package/lib/util/negateValue.js +2 -2
- package/lib/util/normalizeConfig.js +22 -22
- package/lib/util/pluginUtils.js +38 -40
- package/lib/util/prefixSelector.js +22 -8
- package/lib/util/resolveConfig.js +8 -10
- package/oxide-node-api-shim/index.js +21 -0
- package/oxide-node-api-shim/package.json +5 -0
- package/package.json +32 -19
- package/peers/index.js +61 -42
- package/resolveConfig.d.ts +11 -2
- package/scripts/swap-engines.js +40 -0
- package/src/cli/build/index.js +6 -2
- package/src/cli/build/plugin.js +14 -9
- package/src/cli/index.js +234 -3
- package/src/cli.js +4 -220
- package/src/corePlugins.js +31 -3
- package/src/index.js +4 -46
- package/src/lib/content.js +12 -17
- package/src/lib/defaultExtractor.js +9 -3
- package/src/lib/detectNesting.js +9 -1
- package/src/lib/expandTailwindAtRules.js +37 -6
- package/src/lib/generateRules.js +90 -28
- package/src/lib/offsets.js +104 -1
- package/src/lib/remap-bitfield.js +82 -0
- package/src/lib/setupContextUtils.js +97 -55
- package/src/lib/setupTrackingContext.js +31 -6
- package/src/lib/sharedState.js +17 -0
- package/src/oxide/cli/build/deps.ts +91 -0
- package/src/oxide/cli/build/index.ts +47 -0
- package/src/oxide/cli/build/plugin.ts +436 -0
- package/src/oxide/cli/build/utils.ts +74 -0
- package/src/oxide/cli/build/watching.ts +225 -0
- package/src/oxide/cli/help/index.ts +69 -0
- package/src/oxide/cli/index.ts +212 -0
- package/src/oxide/cli/init/index.ts +32 -0
- package/src/oxide/cli.ts +1 -0
- package/src/oxide/postcss-plugin.ts +1 -0
- package/src/plugin.js +107 -0
- package/src/util/color.js +17 -2
- package/src/util/dataTypes.js +29 -4
- package/src/util/formatVariantSelector.js +215 -122
- package/src/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +1 -1
- package/src/util/negateValue.js +1 -1
- package/src/util/pluginUtils.js +22 -19
- package/src/util/prefixSelector.js +28 -10
- package/src/util/resolveConfig.js +0 -2
- package/stubs/defaultConfig.stub.js +149 -165
- package/types/config.d.ts +7 -2
- package/types/generated/default-theme.d.ts +77 -77
- package/lib/cli/shared.js +0 -12
- package/scripts/install-integrations.js +0 -27
- package/scripts/rebuildFixtures.js +0 -68
- package/src/cli/shared.js +0 -5
|
@@ -6,12 +6,14 @@ Object.defineProperty(exports, "default", {
|
|
|
6
6
|
enumerable: true,
|
|
7
7
|
get: ()=>expandTailwindAtRules
|
|
8
8
|
});
|
|
9
|
+
const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
|
|
9
10
|
const _quickLru = /*#__PURE__*/ _interopRequireDefault(require("quick-lru"));
|
|
10
11
|
const _sharedState = /*#__PURE__*/ _interopRequireWildcard(require("./sharedState"));
|
|
11
12
|
const _generateRules = require("./generateRules");
|
|
12
13
|
const _log = /*#__PURE__*/ _interopRequireDefault(require("../util/log"));
|
|
13
14
|
const _cloneNodes = /*#__PURE__*/ _interopRequireDefault(require("../util/cloneNodes"));
|
|
14
15
|
const _defaultExtractor = require("./defaultExtractor");
|
|
16
|
+
const _oxide = /*#__PURE__*/ _interopRequireDefault(require("@tailwindcss/oxide"));
|
|
15
17
|
function _interopRequireDefault(obj) {
|
|
16
18
|
return obj && obj.__esModule ? obj : {
|
|
17
19
|
default: obj
|
|
@@ -142,24 +144,48 @@ function expandTailwindAtRules(context) {
|
|
|
142
144
|
if (Object.values(layerNodes).every((n)=>n === null)) {
|
|
143
145
|
return root;
|
|
144
146
|
}
|
|
147
|
+
var _context_candidates;
|
|
145
148
|
// ---
|
|
146
149
|
// Find potential rules in changed files
|
|
147
150
|
let candidates = new Set([
|
|
151
|
+
...(_context_candidates = context.candidates) !== null && _context_candidates !== void 0 ? _context_candidates : [],
|
|
148
152
|
_sharedState.NOT_ON_DEMAND
|
|
149
153
|
]);
|
|
150
154
|
let seen = new Set();
|
|
151
155
|
env.DEBUG && console.time("Reading changed files");
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
let
|
|
155
|
-
|
|
156
|
+
if (env.OXIDE) {
|
|
157
|
+
// TODO: Pass through or implement `extractor`
|
|
158
|
+
for (let candidate of _oxide.default.parseCandidateStringsFromFiles(context.changedContent)){
|
|
159
|
+
candidates.add(candidate);
|
|
160
|
+
}
|
|
161
|
+
// for (let { file, content, extension } of context.changedContent) {
|
|
162
|
+
// let transformer = getTransformer(context.tailwindConfig, extension)
|
|
163
|
+
// let extractor = getExtractor(context, extension)
|
|
164
|
+
// getClassCandidatesOxide(file, transformer(content), extractor, candidates, seen)
|
|
165
|
+
// }
|
|
166
|
+
} else {
|
|
167
|
+
for (let { file , content , extension } of context.changedContent){
|
|
168
|
+
let transformer = getTransformer(context.tailwindConfig, extension);
|
|
169
|
+
let extractor = getExtractor(context, extension);
|
|
170
|
+
content = file ? _fs.default.readFileSync(file, "utf8") : content;
|
|
171
|
+
getClassCandidates(transformer(content), extractor, candidates, seen);
|
|
172
|
+
}
|
|
156
173
|
}
|
|
157
174
|
env.DEBUG && console.timeEnd("Reading changed files");
|
|
158
175
|
// ---
|
|
159
176
|
// Generate the actual CSS
|
|
160
177
|
let classCacheCount = context.classCache.size;
|
|
161
178
|
env.DEBUG && console.time("Generate rules");
|
|
162
|
-
|
|
179
|
+
env.DEBUG && console.time("Sorting candidates");
|
|
180
|
+
let sortedCandidates = env.OXIDE ? candidates : new Set([
|
|
181
|
+
...candidates
|
|
182
|
+
].sort((a, z)=>{
|
|
183
|
+
if (a === z) return 0;
|
|
184
|
+
if (a < z) return -1;
|
|
185
|
+
return 1;
|
|
186
|
+
}));
|
|
187
|
+
env.DEBUG && console.timeEnd("Sorting candidates");
|
|
188
|
+
(0, _generateRules.generateRules)(sortedCandidates, context);
|
|
163
189
|
env.DEBUG && console.timeEnd("Generate rules");
|
|
164
190
|
// We only ever add to the classCache, so if it didn't grow, there is nothing new.
|
|
165
191
|
env.DEBUG && console.time("Build stylesheet");
|
|
@@ -199,8 +225,8 @@ function expandTailwindAtRules(context) {
|
|
|
199
225
|
}
|
|
200
226
|
// We do post-filtering to not alter the emitted order of the variants
|
|
201
227
|
const variantNodes = Array.from(screenNodes).filter((node)=>{
|
|
202
|
-
var
|
|
203
|
-
const parentLayer = (
|
|
228
|
+
var _node_raws_tailwind;
|
|
229
|
+
const parentLayer = (_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer;
|
|
204
230
|
if (parentLayer === "components") {
|
|
205
231
|
return layerNodes.components !== null;
|
|
206
232
|
}
|
|
@@ -221,8 +247,8 @@ function expandTailwindAtRules(context) {
|
|
|
221
247
|
}
|
|
222
248
|
// If we've got a utility layer and no utilities are generated there's likely something wrong
|
|
223
249
|
const hasUtilityVariants = variantNodes.some((node)=>{
|
|
224
|
-
var
|
|
225
|
-
return ((
|
|
250
|
+
var _node_raws_tailwind;
|
|
251
|
+
return ((_node_raws_tailwind = node.raws.tailwind) === null || _node_raws_tailwind === void 0 ? void 0 : _node_raws_tailwind.parentLayer) === "utilities";
|
|
226
252
|
});
|
|
227
253
|
if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
|
|
228
254
|
_log.default.warn("content-problems", [
|
|
@@ -17,9 +17,9 @@ function findAtConfigPath(root, result) {
|
|
|
17
17
|
let configPath = null;
|
|
18
18
|
let relativeTo = null;
|
|
19
19
|
root.walkAtRules("config", (rule)=>{
|
|
20
|
-
var
|
|
21
|
-
var
|
|
22
|
-
relativeTo = (
|
|
20
|
+
var _rule_source;
|
|
21
|
+
var _rule_source_input_file, _ref;
|
|
22
|
+
relativeTo = (_ref = (_rule_source_input_file = (_rule_source = rule.source) === null || _rule_source === void 0 ? void 0 : _rule_source.input.file) !== null && _rule_source_input_file !== void 0 ? _rule_source_input_file : result.opts.from) !== null && _ref !== void 0 ? _ref : null;
|
|
23
23
|
if (relativeTo === null) {
|
|
24
24
|
throw rule.error("The `@config` directive cannot be used without setting `from` in your PostCSS config.");
|
|
25
25
|
}
|
package/lib/lib/generateRules.js
CHANGED
|
@@ -25,7 +25,7 @@ const _formatVariantSelector = require("../util/formatVariantSelector");
|
|
|
25
25
|
const _nameClass = require("../util/nameClass");
|
|
26
26
|
const _dataTypes = require("../util/dataTypes");
|
|
27
27
|
const _setupContextUtils = require("./setupContextUtils");
|
|
28
|
-
const
|
|
28
|
+
const _isSyntacticallyValidPropertyValue = /*#__PURE__*/ _interopRequireDefault(require("../util/isSyntacticallyValidPropertyValue"));
|
|
29
29
|
const _splitAtTopLevelOnlyJs = require("../util/splitAtTopLevelOnly.js");
|
|
30
30
|
const _featureFlags = require("../featureFlags");
|
|
31
31
|
function _interopRequireDefault(obj) {
|
|
@@ -198,10 +198,16 @@ function applyVariant(variant, matches, context) {
|
|
|
198
198
|
};
|
|
199
199
|
// Retrieve "modifier"
|
|
200
200
|
{
|
|
201
|
-
let
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
201
|
+
let [baseVariant, ...modifiers] = (0, _splitAtTopLevelOnlyJs.splitAtTopLevelOnly)(variant, "/");
|
|
202
|
+
// This is a hack to support variants with `/` in them, like `ar-1/10/20:text-red-500`
|
|
203
|
+
// In this case 1/10 is a value but /20 is a modifier
|
|
204
|
+
if (modifiers.length > 1) {
|
|
205
|
+
baseVariant = baseVariant + "/" + modifiers.slice(0, -1).join("/");
|
|
206
|
+
modifiers = modifiers.slice(-1);
|
|
207
|
+
}
|
|
208
|
+
if (modifiers.length && !context.variantMap.has(variant)) {
|
|
209
|
+
variant = baseVariant;
|
|
210
|
+
args.modifier = modifiers[0];
|
|
205
211
|
if (!(0, _featureFlags.flagEnabled)(context.tailwindConfig, "generalizedModifiers")) {
|
|
206
212
|
return [];
|
|
207
213
|
}
|
|
@@ -216,9 +222,9 @@ function applyVariant(variant, matches, context) {
|
|
|
216
222
|
// But we don't want:
|
|
217
223
|
// @-[200px] (`-` is incorrect)
|
|
218
224
|
// group[:hover] (`-` is missing)
|
|
219
|
-
let
|
|
220
|
-
if (
|
|
221
|
-
let [, char, seperator, value] =
|
|
225
|
+
let match = /(.)(-?)\[(.*)\]/g.exec(variant);
|
|
226
|
+
if (match) {
|
|
227
|
+
let [, char, seperator, value] = match;
|
|
222
228
|
// @-[200px] case
|
|
223
229
|
if (char === "@" && seperator === "-") return [];
|
|
224
230
|
// group[:hover] case
|
|
@@ -243,6 +249,7 @@ function applyVariant(variant, matches, context) {
|
|
|
243
249
|
]);
|
|
244
250
|
}
|
|
245
251
|
if (context.variantMap.has(variant)) {
|
|
252
|
+
let isArbitraryVariant = isArbitraryValue(variant);
|
|
246
253
|
let variantFunctionTuples = context.variantMap.get(variant).slice();
|
|
247
254
|
let result = [];
|
|
248
255
|
for (let [meta, rule] of matches){
|
|
@@ -299,7 +306,10 @@ function applyVariant(variant, matches, context) {
|
|
|
299
306
|
clone.append(wrapper);
|
|
300
307
|
},
|
|
301
308
|
format (selectorFormat) {
|
|
302
|
-
collectedFormats.push(
|
|
309
|
+
collectedFormats.push({
|
|
310
|
+
format: selectorFormat,
|
|
311
|
+
isArbitraryVariant
|
|
312
|
+
});
|
|
303
313
|
},
|
|
304
314
|
args
|
|
305
315
|
});
|
|
@@ -322,7 +332,10 @@ function applyVariant(variant, matches, context) {
|
|
|
322
332
|
continue;
|
|
323
333
|
}
|
|
324
334
|
if (typeof ruleWithVariant === "string") {
|
|
325
|
-
collectedFormats.push(
|
|
335
|
+
collectedFormats.push({
|
|
336
|
+
format: ruleWithVariant,
|
|
337
|
+
isArbitraryVariant
|
|
338
|
+
});
|
|
326
339
|
}
|
|
327
340
|
if (ruleWithVariant === null) {
|
|
328
341
|
continue;
|
|
@@ -358,7 +371,10 @@ function applyVariant(variant, matches, context) {
|
|
|
358
371
|
// modified (by plugin): .foo .foo\\:markdown > p
|
|
359
372
|
// rebuiltBase (internal): .foo\\:markdown > p
|
|
360
373
|
// format: .foo &
|
|
361
|
-
collectedFormats.push(
|
|
374
|
+
collectedFormats.push({
|
|
375
|
+
format: modified.replace(rebuiltBase, "&"),
|
|
376
|
+
isArbitraryVariant
|
|
377
|
+
});
|
|
362
378
|
rule.selector = before;
|
|
363
379
|
});
|
|
364
380
|
}
|
|
@@ -370,13 +386,12 @@ function applyVariant(variant, matches, context) {
|
|
|
370
386
|
...clone.nodes[0].raws.tailwind,
|
|
371
387
|
parentLayer: meta.layer
|
|
372
388
|
};
|
|
373
|
-
var
|
|
389
|
+
var _meta_collectedFormats;
|
|
374
390
|
let withOffset = [
|
|
375
391
|
{
|
|
376
392
|
...meta,
|
|
377
393
|
sort: context.offsets.applyVariantOffset(meta.sort, variantSort, Object.assign(args, context.variantOptions.get(variant))),
|
|
378
|
-
collectedFormats: ((
|
|
379
|
-
isArbitraryVariant: isArbitraryValue(variant)
|
|
394
|
+
collectedFormats: ((_meta_collectedFormats = meta.collectedFormats) !== null && _meta_collectedFormats !== void 0 ? _meta_collectedFormats : []).concat(collectedFormats)
|
|
380
395
|
},
|
|
381
396
|
clone.nodes[0]
|
|
382
397
|
];
|
|
@@ -434,7 +449,7 @@ function isValidPropName(name) {
|
|
|
434
449
|
function isParsableNode(node) {
|
|
435
450
|
let isParsable = true;
|
|
436
451
|
node.walkDecls((decl)=>{
|
|
437
|
-
if (!isParsableCssValue(decl.
|
|
452
|
+
if (!isParsableCssValue(decl.prop, decl.value)) {
|
|
438
453
|
isParsable = false;
|
|
439
454
|
return false;
|
|
440
455
|
}
|
|
@@ -456,15 +471,15 @@ function isParsableCssValue(property, value) {
|
|
|
456
471
|
}
|
|
457
472
|
}
|
|
458
473
|
function extractArbitraryProperty(classCandidate, context) {
|
|
459
|
-
var
|
|
460
|
-
let [, property, value] = (
|
|
474
|
+
var _classCandidate_match;
|
|
475
|
+
let [, property, value] = (_classCandidate_match = classCandidate.match(/^\[([a-zA-Z0-9-_]+):(\S+)\]$/)) !== null && _classCandidate_match !== void 0 ? _classCandidate_match : [];
|
|
461
476
|
if (value === undefined) {
|
|
462
477
|
return null;
|
|
463
478
|
}
|
|
464
479
|
if (!isValidPropName(property)) {
|
|
465
480
|
return null;
|
|
466
481
|
}
|
|
467
|
-
if (!(0,
|
|
482
|
+
if (!(0, _isSyntacticallyValidPropertyValue.default)(value)) {
|
|
468
483
|
return null;
|
|
469
484
|
}
|
|
470
485
|
let normalized = (0, _dataTypes.normalize)(value);
|
|
@@ -535,12 +550,12 @@ function splitWithSeparator(input, separator) {
|
|
|
535
550
|
}
|
|
536
551
|
function* recordCandidates(matches, classCandidate) {
|
|
537
552
|
for (const match of matches){
|
|
538
|
-
var
|
|
539
|
-
var
|
|
553
|
+
var _match__options;
|
|
554
|
+
var _match__options_preserveSource;
|
|
540
555
|
match[1].raws.tailwind = {
|
|
541
556
|
...match[1].raws.tailwind,
|
|
542
557
|
classCandidate,
|
|
543
|
-
preserveSource: (
|
|
558
|
+
preserveSource: (_match__options_preserveSource = (_match__options = match[0].options) === null || _match__options === void 0 ? void 0 : _match__options.preserveSource) !== null && _match__options_preserveSource !== void 0 ? _match__options_preserveSource : false
|
|
544
559
|
};
|
|
545
560
|
yield match;
|
|
546
561
|
}
|
|
@@ -614,9 +629,9 @@ function* resolveMatches(candidate, context, original = candidate) {
|
|
|
614
629
|
}
|
|
615
630
|
}
|
|
616
631
|
if (matchesPerPlugin.length > 0) {
|
|
617
|
-
var
|
|
618
|
-
var
|
|
619
|
-
let matchingTypes = Array.from((0, _pluginUtils.getMatchingTypes)((
|
|
632
|
+
var _sort_options;
|
|
633
|
+
var _sort_options_types, _sort_options1;
|
|
634
|
+
let matchingTypes = Array.from((0, _pluginUtils.getMatchingTypes)((_sort_options_types = (_sort_options = sort.options) === null || _sort_options === void 0 ? void 0 : _sort_options.types) !== null && _sort_options_types !== void 0 ? _sort_options_types : [], modifier, (_sort_options1 = sort.options) !== null && _sort_options1 !== void 0 ? _sort_options1 : {}, context.tailwindConfig)).map(([_, type])=>type);
|
|
620
635
|
if (matchingTypes.length > 0) {
|
|
621
636
|
typesByMatches.set(matchesPerPlugin, matchingTypes);
|
|
622
637
|
}
|
|
@@ -656,18 +671,18 @@ function* resolveMatches(candidate, context, original = candidate) {
|
|
|
656
671
|
});
|
|
657
672
|
});
|
|
658
673
|
}
|
|
659
|
-
var
|
|
674
|
+
var _findFallback;
|
|
660
675
|
// Try to find a fallback plugin, because we already know that multiple plugins matched for
|
|
661
676
|
// the given arbitrary value.
|
|
662
|
-
let fallback = (
|
|
677
|
+
let fallback = (_findFallback = findFallback(withoutAny)) !== null && _findFallback !== void 0 ? _findFallback : findFallback(withAny);
|
|
663
678
|
if (fallback) {
|
|
664
679
|
matches = [
|
|
665
680
|
fallback
|
|
666
681
|
];
|
|
667
682
|
} else {
|
|
668
|
-
var
|
|
683
|
+
var _typesByMatches_get;
|
|
669
684
|
let typesPerPlugin = matches.map((match)=>new Set([
|
|
670
|
-
...(
|
|
685
|
+
...(_typesByMatches_get = typesByMatches.get(match)) !== null && _typesByMatches_get !== void 0 ? _typesByMatches_get : []
|
|
671
686
|
]));
|
|
672
687
|
// Remove duplicates, so that we can detect proper unique types for each plugin.
|
|
673
688
|
for (let pluginTypes of typesPerPlugin){
|
|
@@ -718,31 +733,71 @@ function* resolveMatches(candidate, context, original = candidate) {
|
|
|
718
733
|
candidate
|
|
719
734
|
};
|
|
720
735
|
// Apply final format selector
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
var ref1;
|
|
732
|
-
rule.selector = (0, _formatVariantSelector.finalizeSelector)(finalFormat, {
|
|
733
|
-
selector: rule.selector,
|
|
734
|
-
candidate: original,
|
|
735
|
-
base: candidate.split(new RegExp(`\\${(ref1 = context === null || context === void 0 ? void 0 : (ref = context.tailwindConfig) === null || ref === void 0 ? void 0 : ref.separator) !== null && ref1 !== void 0 ? ref1 : ":"}(?![^[]*\\])`)).pop(),
|
|
736
|
-
isArbitraryVariant: match[0].isArbitraryVariant,
|
|
737
|
-
context
|
|
738
|
-
});
|
|
739
|
-
});
|
|
740
|
-
match[1] = container.nodes[0];
|
|
736
|
+
match = applyFinalFormat(match, {
|
|
737
|
+
context,
|
|
738
|
+
candidate,
|
|
739
|
+
original
|
|
740
|
+
});
|
|
741
|
+
// Skip rules with invalid selectors
|
|
742
|
+
// This will cause the candidate to be added to the "not class"
|
|
743
|
+
// cache skipping it entirely for future builds
|
|
744
|
+
if (match === null) {
|
|
745
|
+
continue;
|
|
741
746
|
}
|
|
742
747
|
yield match;
|
|
743
748
|
}
|
|
744
749
|
}
|
|
745
750
|
}
|
|
751
|
+
function applyFinalFormat(match, { context , candidate , original }) {
|
|
752
|
+
if (!match[0].collectedFormats) {
|
|
753
|
+
return match;
|
|
754
|
+
}
|
|
755
|
+
let isValid = true;
|
|
756
|
+
let finalFormat;
|
|
757
|
+
try {
|
|
758
|
+
finalFormat = (0, _formatVariantSelector.formatVariantSelector)(match[0].collectedFormats, {
|
|
759
|
+
context,
|
|
760
|
+
candidate
|
|
761
|
+
});
|
|
762
|
+
} catch {
|
|
763
|
+
// The format selector we produced is invalid
|
|
764
|
+
// This could be because:
|
|
765
|
+
// - A bug exists
|
|
766
|
+
// - A plugin introduced an invalid variant selector (ex: `addVariant('foo', '&;foo')`)
|
|
767
|
+
// - The user used an invalid arbitrary variant (ex: `[&;foo]:underline`)
|
|
768
|
+
// Either way the build will fail because of this
|
|
769
|
+
// We would rather that the build pass "silently" given that this could
|
|
770
|
+
// happen because of picking up invalid things when scanning content
|
|
771
|
+
// So we'll throw out the candidate instead
|
|
772
|
+
return null;
|
|
773
|
+
}
|
|
774
|
+
let container = _postcss.default.root({
|
|
775
|
+
nodes: [
|
|
776
|
+
match[1].clone()
|
|
777
|
+
]
|
|
778
|
+
});
|
|
779
|
+
container.walkRules((rule)=>{
|
|
780
|
+
if (inKeyframes(rule)) {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
try {
|
|
784
|
+
rule.selector = (0, _formatVariantSelector.finalizeSelector)(rule.selector, finalFormat, {
|
|
785
|
+
candidate: original,
|
|
786
|
+
context
|
|
787
|
+
});
|
|
788
|
+
} catch {
|
|
789
|
+
// If this selector is invalid we also want to skip it
|
|
790
|
+
// But it's likely that being invalid here means there's a bug in a plugin rather than too loosely matching content
|
|
791
|
+
isValid = false;
|
|
792
|
+
return false;
|
|
793
|
+
}
|
|
794
|
+
});
|
|
795
|
+
if (!isValid) {
|
|
796
|
+
return null;
|
|
797
|
+
}
|
|
798
|
+
match[1] = container.nodes[0];
|
|
799
|
+
return match;
|
|
800
|
+
}
|
|
746
801
|
function inKeyframes(rule) {
|
|
747
802
|
return rule.parent && rule.parent.type === "atrule" && rule.parent.name === "keyframes";
|
|
748
803
|
}
|
|
@@ -787,8 +842,8 @@ function generateRules(candidates, context) {
|
|
|
787
842
|
continue;
|
|
788
843
|
}
|
|
789
844
|
context.classCache.set(candidate, matches);
|
|
790
|
-
var
|
|
791
|
-
let rules = (
|
|
845
|
+
var _context_candidateRuleCache_get;
|
|
846
|
+
let rules = (_context_candidateRuleCache_get = context.candidateRuleCache.get(candidate)) !== null && _context_candidateRuleCache_get !== void 0 ? _context_candidateRuleCache_get : new Set();
|
|
792
847
|
context.candidateRuleCache.set(candidate, rules);
|
|
793
848
|
for (const match of matches){
|
|
794
849
|
let [{ sort , options }, rule] = match;
|
package/lib/lib/offsets.js
CHANGED
|
@@ -8,6 +8,7 @@ Object.defineProperty(exports, "Offsets", {
|
|
|
8
8
|
get: ()=>Offsets
|
|
9
9
|
});
|
|
10
10
|
const _bigSign = /*#__PURE__*/ _interopRequireDefault(require("../util/bigSign"));
|
|
11
|
+
const _remapBitfieldJs = require("./remap-bitfield.js");
|
|
11
12
|
function _interopRequireDefault(obj) {
|
|
12
13
|
return obj && obj.__esModule ? obj : {
|
|
13
14
|
default: obj
|
|
@@ -96,6 +97,7 @@ class Offsets {
|
|
|
96
97
|
* @param {VariantOption} options
|
|
97
98
|
* @returns {RuleOffset}
|
|
98
99
|
*/ applyVariantOffset(rule, variant, options) {
|
|
100
|
+
options.variant = variant.variants;
|
|
99
101
|
return {
|
|
100
102
|
...rule,
|
|
101
103
|
layer: "variants",
|
|
@@ -153,7 +155,7 @@ class Offsets {
|
|
|
153
155
|
this.reservedVariantBits += BigInt(fnCount);
|
|
154
156
|
return {
|
|
155
157
|
...this.create("variants"),
|
|
156
|
-
variants:
|
|
158
|
+
variants: this.variantOffsets.get(variant)
|
|
157
159
|
};
|
|
158
160
|
}
|
|
159
161
|
/**
|
|
@@ -165,11 +167,29 @@ class Offsets {
|
|
|
165
167
|
if (a.layer !== b.layer) {
|
|
166
168
|
return this.layerPositions[a.layer] - this.layerPositions[b.layer];
|
|
167
169
|
}
|
|
170
|
+
// When sorting the `variants` layer, we need to sort based on the parent layer as well within
|
|
171
|
+
// this variants layer.
|
|
172
|
+
if (a.parentLayer !== b.parentLayer) {
|
|
173
|
+
return this.layerPositions[a.parentLayer] - this.layerPositions[b.parentLayer];
|
|
174
|
+
}
|
|
168
175
|
// Sort based on the sorting function
|
|
169
176
|
for (let aOptions of a.options){
|
|
170
177
|
for (let bOptions of b.options){
|
|
171
178
|
if (aOptions.id !== bOptions.id) continue;
|
|
172
179
|
if (!aOptions.sort || !bOptions.sort) continue;
|
|
180
|
+
var _max;
|
|
181
|
+
let maxFnVariant = (_max = max([
|
|
182
|
+
aOptions.variant,
|
|
183
|
+
bOptions.variant
|
|
184
|
+
])) !== null && _max !== void 0 ? _max : 0n;
|
|
185
|
+
// Create a mask of 0s from bits 1..N where N represents the mask of the Nth bit
|
|
186
|
+
let mask = ~(maxFnVariant | maxFnVariant - 1n);
|
|
187
|
+
let aVariantsAfterFn = a.variants & mask;
|
|
188
|
+
let bVariantsAfterFn = b.variants & mask;
|
|
189
|
+
// If the variants the same, we _can_ sort them
|
|
190
|
+
if (aVariantsAfterFn !== bVariantsAfterFn) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
173
193
|
let result = aOptions.sort({
|
|
174
194
|
value: aOptions.value,
|
|
175
195
|
modifier: aOptions.modifier
|
|
@@ -196,10 +216,57 @@ class Offsets {
|
|
|
196
216
|
return a.index - b.index;
|
|
197
217
|
}
|
|
198
218
|
/**
|
|
219
|
+
* Arbitrary variants are recorded in the order they're encountered.
|
|
220
|
+
* This means that the order is not stable between environments and sets of content files.
|
|
221
|
+
*
|
|
222
|
+
* In order to make the order stable, we need to remap the arbitrary variant offsets to
|
|
223
|
+
* be in alphabetical order starting from the offset of the first arbitrary variant.
|
|
224
|
+
*/ recalculateVariantOffsets() {
|
|
225
|
+
// Sort the variants by their name
|
|
226
|
+
let variants = Array.from(this.variantOffsets.entries()).filter(([v])=>v.startsWith("[")).sort(([a], [z])=>fastCompare(a, z));
|
|
227
|
+
// Sort the list of offsets
|
|
228
|
+
// This is not necessarily a discrete range of numbers which is why
|
|
229
|
+
// we're using sort instead of creating a range from min/max
|
|
230
|
+
let newOffsets = variants.map(([, offset])=>offset).sort((a, z)=>(0, _bigSign.default)(a - z));
|
|
231
|
+
// Create a map from the old offsets to the new offsets in the new sort order
|
|
232
|
+
/** @type {[bigint, bigint][]} */ let mapping = variants.map(([, oldOffset], i)=>[
|
|
233
|
+
oldOffset,
|
|
234
|
+
newOffsets[i]
|
|
235
|
+
]);
|
|
236
|
+
// Remove any variants that will not move letting us skip
|
|
237
|
+
// remapping if everything happens to be in order
|
|
238
|
+
return mapping.filter(([a, z])=>a !== z);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* @template T
|
|
242
|
+
* @param {[RuleOffset, T][]} list
|
|
243
|
+
* @returns {[RuleOffset, T][]}
|
|
244
|
+
*/ remapArbitraryVariantOffsets(list) {
|
|
245
|
+
let mapping = this.recalculateVariantOffsets();
|
|
246
|
+
// No arbitrary variants? Nothing to do.
|
|
247
|
+
// Everyhing already in order? Nothing to do.
|
|
248
|
+
if (mapping.length === 0) {
|
|
249
|
+
return list;
|
|
250
|
+
}
|
|
251
|
+
// Remap every variant offset in the list
|
|
252
|
+
return list.map((item)=>{
|
|
253
|
+
let [offset, rule] = item;
|
|
254
|
+
offset = {
|
|
255
|
+
...offset,
|
|
256
|
+
variants: (0, _remapBitfieldJs.remapBitfield)(offset.variants, mapping)
|
|
257
|
+
};
|
|
258
|
+
return [
|
|
259
|
+
offset,
|
|
260
|
+
rule
|
|
261
|
+
];
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
199
265
|
* @template T
|
|
200
266
|
* @param {[RuleOffset, T][]} list
|
|
201
267
|
* @returns {[RuleOffset, T][]}
|
|
202
268
|
*/ sort(list) {
|
|
269
|
+
list = this.remapArbitraryVariantOffsets(list);
|
|
203
270
|
return list.sort(([a], [b])=>(0, _bigSign.default)(this.compare(a, b)));
|
|
204
271
|
}
|
|
205
272
|
}
|
|
@@ -215,3 +282,23 @@ class Offsets {
|
|
|
215
282
|
}
|
|
216
283
|
return max;
|
|
217
284
|
}
|
|
285
|
+
/**
|
|
286
|
+
* A fast ASCII order string comparison function.
|
|
287
|
+
*
|
|
288
|
+
* Using `.sort()` without a custom compare function is faster
|
|
289
|
+
* But you can only use that if you're sorting an array of
|
|
290
|
+
* only strings. If you're sorting strings inside objects
|
|
291
|
+
* or arrays, you need must use a custom compare function.
|
|
292
|
+
*
|
|
293
|
+
* @param {string} a
|
|
294
|
+
* @param {string} b
|
|
295
|
+
*/ function fastCompare(a, b) {
|
|
296
|
+
let aLen = a.length;
|
|
297
|
+
let bLen = b.length;
|
|
298
|
+
let minLen = aLen < bLen ? aLen : bLen;
|
|
299
|
+
for(let i = 0; i < minLen; i++){
|
|
300
|
+
let cmp = a.charCodeAt(i) - b.charCodeAt(i);
|
|
301
|
+
if (cmp !== 0) return cmp;
|
|
302
|
+
}
|
|
303
|
+
return aLen - bLen;
|
|
304
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* We must remap all the old bits to new bits for each set variant
|
|
4
|
+
* Only arbitrary variants are considered as those are the only
|
|
5
|
+
* ones that need to be re-sorted at this time
|
|
6
|
+
*
|
|
7
|
+
* An iterated process that removes and sets individual bits simultaneously
|
|
8
|
+
* will not work because we may have a new bit that is also a later old bit
|
|
9
|
+
* This means that we would be removing a previously set bit which we don't
|
|
10
|
+
* want to do
|
|
11
|
+
*
|
|
12
|
+
* For example (assume `bN` = `1<<N`)
|
|
13
|
+
* Given the "total" mapping `[[b1, b3], [b2, b4], [b3, b1], [b4, b2]]`
|
|
14
|
+
* The mapping is "total" because:
|
|
15
|
+
* 1. Every input and output is accounted for
|
|
16
|
+
* 2. All combinations are unique
|
|
17
|
+
* 3. No one input maps to multiple outputs and vice versa
|
|
18
|
+
* And, given an offset with all bits set:
|
|
19
|
+
* V = b1 | b2 | b3 | b4
|
|
20
|
+
*
|
|
21
|
+
* Let's explore the issue with removing and setting bits simultaneously:
|
|
22
|
+
* V & ~b1 | b3 = b2 | b3 | b4
|
|
23
|
+
* V & ~b2 | b4 = b3 | b4
|
|
24
|
+
* V & ~b3 | b1 = b1 | b4
|
|
25
|
+
* V & ~b4 | b2 = b1 | b2
|
|
26
|
+
*
|
|
27
|
+
* As you can see, we end up with the wrong result.
|
|
28
|
+
* This is because we're removing a bit that was previously set.
|
|
29
|
+
* And, thus the final result is missing b3 and b4.
|
|
30
|
+
*
|
|
31
|
+
* Now, let's explore the issue with removing the bits first:
|
|
32
|
+
* V & ~b1 = b2 | b3 | b4
|
|
33
|
+
* V & ~b2 = b3 | b4
|
|
34
|
+
* V & ~b3 = b4
|
|
35
|
+
* V & ~b4 = 0
|
|
36
|
+
*
|
|
37
|
+
* And then setting the bits:
|
|
38
|
+
* V | b3 = b3
|
|
39
|
+
* V | b4 = b3 | b4
|
|
40
|
+
* V | b1 = b1 | b3 | b4
|
|
41
|
+
* V | b2 = b1 | b2 | b3 | b4
|
|
42
|
+
*
|
|
43
|
+
* We get the correct result because we're not removing any bits that were
|
|
44
|
+
* previously set thus properly remapping the bits to the new order
|
|
45
|
+
*
|
|
46
|
+
* To collect this into a single operation that can be done simultaneously
|
|
47
|
+
* we must first create a mask for the old bits that are set and a mask for
|
|
48
|
+
* the new bits that are set. Then we can remove the old bits and set the new
|
|
49
|
+
* bits simultaneously in a "single" operation like so:
|
|
50
|
+
* OldMask = b1 | b2 | b3 | b4
|
|
51
|
+
* NewMask = b3 | b4 | b1 | b2
|
|
52
|
+
*
|
|
53
|
+
* So this:
|
|
54
|
+
* V & ~oldMask | newMask
|
|
55
|
+
*
|
|
56
|
+
* Expands to this:
|
|
57
|
+
* V & ~b1 & ~b2 & ~b3 & ~b4 | b3 | b4 | b1 | b2
|
|
58
|
+
*
|
|
59
|
+
* Which becomes this:
|
|
60
|
+
* b1 | b2 | b3 | b4
|
|
61
|
+
*
|
|
62
|
+
* Which is the correct result!
|
|
63
|
+
*
|
|
64
|
+
* @param {bigint} num
|
|
65
|
+
* @param {[bigint, bigint][]} mapping
|
|
66
|
+
*/ "use strict";
|
|
67
|
+
Object.defineProperty(exports, "__esModule", {
|
|
68
|
+
value: true
|
|
69
|
+
});
|
|
70
|
+
Object.defineProperty(exports, "remapBitfield", {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
get: ()=>remapBitfield
|
|
73
|
+
});
|
|
74
|
+
function remapBitfield(num, mapping) {
|
|
75
|
+
// Create masks for the old and new bits that are set
|
|
76
|
+
let oldMask = 0n;
|
|
77
|
+
let newMask = 0n;
|
|
78
|
+
for (let [oldBit, newBit] of mapping){
|
|
79
|
+
if (num & oldBit) {
|
|
80
|
+
oldMask = oldMask | oldBit;
|
|
81
|
+
newMask = newMask | newBit;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Remove all old bits
|
|
85
|
+
// Set all new bits
|
|
86
|
+
return num & ~oldMask | newMask;
|
|
87
|
+
}
|
|
@@ -99,8 +99,8 @@ function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
99
99
|
if ((0, _featureFlags.flagEnabled)(tailwindConfig, "optimizeUniversalDefaults")) {
|
|
100
100
|
for (let universal of universals){
|
|
101
101
|
/** @type {Map<string, Set<string>>} */ let selectorGroups = new Map();
|
|
102
|
-
var
|
|
103
|
-
let rules = (
|
|
102
|
+
var _variableNodeMap_get;
|
|
103
|
+
let rules = (_variableNodeMap_get = variableNodeMap.get(universal.params)) !== null && _variableNodeMap_get !== void 0 ? _variableNodeMap_get : [];
|
|
104
104
|
for (let rule of rules){
|
|
105
105
|
for (let selector of extractElementSelector(rule.selector)){
|
|
106
106
|
// If selector contains a vendor prefix after a pseudo element or class,
|
|
@@ -108,8 +108,8 @@ function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
108
108
|
// a single rule will cause browsers that do not understand the
|
|
109
109
|
// vendor prefix to throw out the whole rule
|
|
110
110
|
let selectorGroupName = selector.includes(":-") || selector.includes("::-") ? selector : "__DEFAULT__";
|
|
111
|
-
var
|
|
112
|
-
let selectors = (
|
|
111
|
+
var _selectorGroups_get;
|
|
112
|
+
let selectors = (_selectorGroups_get = selectorGroups.get(selectorGroupName)) !== null && _selectorGroups_get !== void 0 ? _selectorGroups_get : new Set();
|
|
113
113
|
selectorGroups.set(selectorGroupName, selectors);
|
|
114
114
|
selectors.add(selector);
|
|
115
115
|
}
|