tailwindcss 3.1.7 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +12 -8
  2. package/lib/cli/build/deps.js +54 -0
  3. package/lib/cli/build/index.js +44 -0
  4. package/lib/cli/build/plugin.js +335 -0
  5. package/lib/cli/build/utils.js +78 -0
  6. package/lib/cli/build/watching.js +113 -0
  7. package/lib/cli/help/index.js +71 -0
  8. package/lib/cli/index.js +18 -0
  9. package/lib/cli/init/index.js +46 -0
  10. package/lib/cli/shared.js +12 -0
  11. package/lib/cli.js +11 -590
  12. package/lib/corePlugins.js +332 -108
  13. package/lib/css/preflight.css +5 -0
  14. package/lib/featureFlags.js +7 -4
  15. package/lib/index.js +6 -1
  16. package/lib/lib/content.js +167 -0
  17. package/lib/lib/defaultExtractor.js +15 -10
  18. package/lib/lib/detectNesting.js +2 -2
  19. package/lib/lib/evaluateTailwindFunctions.js +17 -1
  20. package/lib/lib/expandApplyAtRules.js +71 -37
  21. package/lib/lib/expandTailwindAtRules.js +10 -42
  22. package/lib/lib/findAtConfigPath.js +44 -0
  23. package/lib/lib/generateRules.js +181 -96
  24. package/lib/lib/normalizeTailwindDirectives.js +1 -1
  25. package/lib/lib/offsets.js +217 -0
  26. package/lib/lib/regex.js +1 -1
  27. package/lib/lib/setupContextUtils.js +339 -100
  28. package/lib/lib/setupTrackingContext.js +5 -39
  29. package/lib/lib/sharedState.js +2 -0
  30. package/lib/public/colors.js +1 -1
  31. package/lib/util/buildMediaQuery.js +6 -3
  32. package/lib/util/configurePlugins.js +1 -1
  33. package/lib/util/dataTypes.js +15 -19
  34. package/lib/util/formatVariantSelector.js +92 -8
  35. package/lib/util/getAllConfigs.js +14 -3
  36. package/lib/util/isValidArbitraryValue.js +1 -1
  37. package/lib/util/nameClass.js +3 -0
  38. package/lib/util/negateValue.js +15 -2
  39. package/lib/util/normalizeConfig.js +17 -3
  40. package/lib/util/normalizeScreens.js +100 -3
  41. package/lib/util/parseAnimationValue.js +1 -1
  42. package/lib/util/parseBoxShadowValue.js +1 -1
  43. package/lib/util/parseDependency.js +33 -54
  44. package/lib/util/parseGlob.js +34 -0
  45. package/lib/util/parseObjectStyles.js +1 -1
  46. package/lib/util/pluginUtils.js +86 -17
  47. package/lib/util/resolveConfig.js +3 -3
  48. package/lib/util/splitAtTopLevelOnly.js +31 -81
  49. package/lib/util/transformThemeValue.js +9 -2
  50. package/lib/util/validateConfig.js +1 -1
  51. package/lib/util/validateFormalSyntax.js +24 -0
  52. package/package.json +14 -12
  53. package/peers/.DS_Store +0 -0
  54. package/peers/.svgo.yml +75 -0
  55. package/peers/index.js +3690 -2274
  56. package/peers/orders/concentric-css.json +299 -0
  57. package/peers/orders/smacss.json +299 -0
  58. package/peers/orders/source.json +295 -0
  59. package/plugin.d.ts +3 -3
  60. package/scripts/release-channel.js +18 -0
  61. package/scripts/release-notes.js +21 -0
  62. package/src/.DS_Store +0 -0
  63. package/src/cli/build/deps.js +56 -0
  64. package/src/cli/build/index.js +45 -0
  65. package/src/cli/build/plugin.js +397 -0
  66. package/src/cli/build/utils.js +76 -0
  67. package/src/cli/build/watching.js +134 -0
  68. package/src/cli/help/index.js +70 -0
  69. package/src/cli/index.js +3 -0
  70. package/src/cli/init/index.js +50 -0
  71. package/src/cli/shared.js +5 -0
  72. package/src/cli.js +4 -696
  73. package/src/corePlugins.js +262 -39
  74. package/src/css/preflight.css +5 -0
  75. package/src/featureFlags.js +12 -2
  76. package/src/index.js +5 -0
  77. package/src/lib/content.js +205 -0
  78. package/src/lib/defaultExtractor.js +3 -0
  79. package/src/lib/evaluateTailwindFunctions.js +22 -1
  80. package/src/lib/expandApplyAtRules.js +76 -29
  81. package/src/lib/expandTailwindAtRules.js +8 -46
  82. package/src/lib/findAtConfigPath.js +48 -0
  83. package/src/lib/generateRules.js +224 -105
  84. package/src/lib/offsets.js +270 -0
  85. package/src/lib/setupContextUtils.js +376 -89
  86. package/src/lib/setupTrackingContext.js +4 -45
  87. package/src/lib/sharedState.js +2 -0
  88. package/src/util/buildMediaQuery.js +5 -3
  89. package/src/util/dataTypes.js +15 -17
  90. package/src/util/formatVariantSelector.js +113 -9
  91. package/src/util/getAllConfigs.js +14 -2
  92. package/src/util/nameClass.js +4 -0
  93. package/src/util/negateValue.js +10 -2
  94. package/src/util/normalizeConfig.js +22 -2
  95. package/src/util/normalizeScreens.js +99 -4
  96. package/src/util/parseBoxShadowValue.js +1 -1
  97. package/src/util/parseDependency.js +37 -42
  98. package/src/util/parseGlob.js +24 -0
  99. package/src/util/pluginUtils.js +90 -14
  100. package/src/util/resolveConfig.js +2 -2
  101. package/src/util/splitAtTopLevelOnly.js +23 -49
  102. package/src/util/transformThemeValue.js +9 -1
  103. package/src/util/validateFormalSyntax.js +34 -0
  104. package/stubs/defaultConfig.stub.js +19 -3
  105. package/tmp.css +11 -0
  106. package/tmp.dependency-graph.js +2 -0
  107. package/tmp.in.css +3 -0
  108. package/tmp.js +0 -0
  109. package/tmp.out.css +524 -0
  110. package/types/config.d.ts +47 -13
  111. package/types/generated/default-theme.d.ts +11 -0
  112. package/CHANGELOG.md +0 -2222
@@ -9,6 +9,7 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
+ getClassNameFromSelector: ()=>getClassNameFromSelector,
12
13
  resolveMatches: ()=>resolveMatches,
13
14
  generateRules: ()=>generateRules
14
15
  });
@@ -88,14 +89,22 @@ function* candidatePermutations(candidate) {
88
89
  let lastIndex = Infinity;
89
90
  while(lastIndex >= 0){
90
91
  let dashIdx;
92
+ let wasSlash = false;
91
93
  if (lastIndex === Infinity && candidate.endsWith("]")) {
92
94
  let bracketIdx = candidate.indexOf("[");
93
95
  // If character before `[` isn't a dash or a slash, this isn't a dynamic class
94
96
  // eg. string[]
95
- dashIdx = [
96
- "-",
97
- "/"
98
- ].includes(candidate[bracketIdx - 1]) ? bracketIdx - 1 : -1;
97
+ if (candidate[bracketIdx - 1] === "-") {
98
+ dashIdx = bracketIdx - 1;
99
+ } else if (candidate[bracketIdx - 1] === "/") {
100
+ dashIdx = bracketIdx - 1;
101
+ wasSlash = true;
102
+ } else {
103
+ dashIdx = -1;
104
+ }
105
+ } else if (lastIndex === Infinity && candidate.includes("/")) {
106
+ dashIdx = candidate.lastIndexOf("/");
107
+ wasSlash = true;
99
108
  } else {
100
109
  dashIdx = candidate.lastIndexOf("-", lastIndex);
101
110
  }
@@ -103,12 +112,16 @@ function* candidatePermutations(candidate) {
103
112
  break;
104
113
  }
105
114
  let prefix = candidate.slice(0, dashIdx);
106
- let modifier = candidate.slice(dashIdx + 1);
115
+ let modifier = candidate.slice(wasSlash ? dashIdx : dashIdx + 1);
116
+ lastIndex = dashIdx - 1;
117
+ // TODO: This feels a bit hacky
118
+ if (prefix === "" || modifier === "/") {
119
+ continue;
120
+ }
107
121
  yield [
108
122
  prefix,
109
123
  modifier
110
124
  ];
111
- lastIndex = dashIdx - 1;
112
125
  }
113
126
  }
114
127
  function applyPrefix(matches, context) {
@@ -179,12 +192,40 @@ function applyVariant(variant, matches, context) {
179
192
  if (matches.length === 0) {
180
193
  return matches;
181
194
  }
182
- let args;
183
- let isArbitraryVariant = false;
184
- // Find partial arbitrary variants
195
+ /** @type {{modifier: string | null, value: string | null}} */ let args = {
196
+ modifier: null,
197
+ value: _sharedState.NONE
198
+ };
199
+ // Retrieve "modifier"
200
+ {
201
+ let match = /(.*)\/(.*)$/g.exec(variant);
202
+ if (match) {
203
+ variant = match[1];
204
+ args.modifier = match[2];
205
+ if (!(0, _featureFlags.flagEnabled)(context.tailwindConfig, "generalizedModifiers")) {
206
+ return [];
207
+ }
208
+ }
209
+ }
210
+ // Retrieve "arbitrary value"
185
211
  if (variant.endsWith("]") && !variant.startsWith("[")) {
186
- args = variant.slice(variant.lastIndexOf("[") + 1, -1);
187
- variant = variant.slice(0, variant.indexOf(args) - 1 /* - */ - 1 /* [ */ );
212
+ // We either have:
213
+ // @[200px]
214
+ // group-[:hover]
215
+ //
216
+ // But we don't want:
217
+ // @-[200px] (`-` is incorrect)
218
+ // group[:hover] (`-` is missing)
219
+ let match1 = /(.)(-?)\[(.*)\]/g.exec(variant);
220
+ if (match1) {
221
+ let [, char, seperator, value] = match1;
222
+ // @-[200px] case
223
+ if (char === "@" && seperator === "-") return [];
224
+ // group[:hover] case
225
+ if (char !== "@" && seperator === "") return [];
226
+ variant = variant.replace(`${seperator}[${value}]`, "");
227
+ args.value = value;
228
+ }
188
229
  }
189
230
  // Register arbitrary variants
190
231
  if (isArbitraryValue(variant) && !context.variantMap.has(variant)) {
@@ -192,16 +233,14 @@ function applyVariant(variant, matches, context) {
192
233
  if (!(0, _setupContextUtils.isValidVariantFormatString)(selector)) {
193
234
  return [];
194
235
  }
195
- isArbitraryVariant = true;
196
236
  let fn = (0, _setupContextUtils.parseVariant)(selector);
197
- let sort = Array.from(context.variantOrder.values()).pop() << 1n;
237
+ let sort = context.offsets.recordVariant(variant);
198
238
  context.variantMap.set(variant, [
199
239
  [
200
240
  sort,
201
241
  fn
202
242
  ]
203
243
  ]);
204
- context.variantOrder.set(variant, sort);
205
244
  }
206
245
  if (context.variantMap.has(variant)) {
207
246
  let variantFunctionTuples = context.variantMap.get(variant).slice();
@@ -273,15 +312,11 @@ function applyVariant(variant, matches, context) {
273
312
  // where you keep handling jobs until everything is done and each job can queue more
274
313
  // jobs if needed.
275
314
  variantFunctionTuples.push([
276
- // TODO: This could have potential bugs if we shift the sort order from variant A far
277
- // enough into the sort space of variant B. The chances are low, but if this happens
278
- // then this might be the place too look at. One potential solution to this problem is
279
- // reserving additional X places for these 'unknown' variants in between.
280
- variantSort | BigInt(idx << ruleWithVariant.length),
315
+ context.offsets.applyParallelOffset(variantSort, idx),
281
316
  variantFunction1,
282
317
  // If the clone has been modified we have to pass that back
283
318
  // though so each rule can use the modified container
284
- clone.clone(),
319
+ clone.clone()
285
320
  ]);
286
321
  }
287
322
  continue;
@@ -339,11 +374,11 @@ function applyVariant(variant, matches, context) {
339
374
  let withOffset = [
340
375
  {
341
376
  ...meta,
342
- sort: variantSort | meta.sort,
377
+ sort: context.offsets.applyVariantOffset(meta.sort, variantSort, Object.assign(args, context.variantOptions.get(variant))),
343
378
  collectedFormats: ((_collectedFormats = meta.collectedFormats) !== null && _collectedFormats !== void 0 ? _collectedFormats : []).concat(collectedFormats),
344
- isArbitraryVariant
379
+ isArbitraryVariant: isArbitraryValue(variant)
345
380
  },
346
- clone.nodes[0],
381
+ clone.nodes[0]
347
382
  ];
348
383
  result.push(withOffset);
349
384
  }
@@ -436,18 +471,19 @@ function extractArbitraryProperty(classCandidate, context) {
436
471
  if (!isParsableCssValue(property, normalized)) {
437
472
  return null;
438
473
  }
474
+ let sort = context.offsets.arbitraryProperty();
439
475
  return [
440
476
  [
441
477
  {
442
- sort: context.arbitraryPropertiesSort,
478
+ sort,
443
479
  layer: "utilities"
444
480
  },
445
481
  ()=>({
446
482
  [(0, _nameClass.asClass)(classCandidate)]: {
447
483
  [property]: normalized
448
484
  }
449
- }),
450
- ],
485
+ })
486
+ ]
451
487
  ];
452
488
  }
453
489
  function* resolveMatchedPlugins(classCandidate, context) {
@@ -495,7 +531,7 @@ function splitWithSeparator(input, separator) {
495
531
  _sharedState.NOT_ON_DEMAND
496
532
  ];
497
533
  }
498
- return Array.from((0, _splitAtTopLevelOnlyJs.splitAtTopLevelOnly)(input, separator));
534
+ return (0, _splitAtTopLevelOnlyJs.splitAtTopLevelOnly)(input, separator);
499
535
  }
500
536
  function* recordCandidates(matches, classCandidate) {
501
537
  for (const match of matches){
@@ -579,48 +615,91 @@ function* resolveMatches(candidate, context, original = candidate) {
579
615
  }
580
616
  if (matchesPerPlugin.length > 0) {
581
617
  var ref;
582
- typesByMatches.set(matchesPerPlugin, (ref = sort.options) === null || ref === void 0 ? void 0 : ref.type);
618
+ var ref1, _options;
619
+ let matchingTypes = Array.from((0, _pluginUtils.getMatchingTypes)((ref1 = (ref = sort.options) === null || ref === void 0 ? void 0 : ref.types) !== null && ref1 !== void 0 ? ref1 : [], modifier, (_options = sort.options) !== null && _options !== void 0 ? _options : {}, context.tailwindConfig)).map(([_, type])=>type);
620
+ if (matchingTypes.length > 0) {
621
+ typesByMatches.set(matchesPerPlugin, matchingTypes);
622
+ }
583
623
  matches.push(matchesPerPlugin);
584
624
  }
585
625
  }
586
626
  if (isArbitraryValue(modifier)) {
587
- // When generated arbitrary values are ambiguous, we can't know
588
- // which to pick so don't generate any utilities for them
589
627
  if (matches.length > 1) {
590
- var ref1;
591
- let typesPerPlugin = matches.map((match)=>new Set([
592
- ...(ref1 = typesByMatches.get(match)) !== null && ref1 !== void 0 ? ref1 : []
593
- ]));
594
- // Remove duplicates, so that we can detect proper unique types for each plugin.
595
- for (let pluginTypes of typesPerPlugin){
596
- for (let type of pluginTypes){
597
- let removeFromOwnGroup = false;
598
- for (let otherGroup of typesPerPlugin){
599
- if (pluginTypes === otherGroup) continue;
600
- if (otherGroup.has(type)) {
601
- otherGroup.delete(type);
602
- removeFromOwnGroup = true;
628
+ // Partition plugins in 2 categories so that we can start searching in the plugins that
629
+ // don't have `any` as a type first.
630
+ let [withAny, withoutAny] = matches.reduce((group, plugin)=>{
631
+ let hasAnyType = plugin.some(([{ options }])=>options.types.some(({ type })=>type === "any"));
632
+ if (hasAnyType) {
633
+ group[0].push(plugin);
634
+ } else {
635
+ group[1].push(plugin);
636
+ }
637
+ return group;
638
+ }, [
639
+ [],
640
+ []
641
+ ]);
642
+ function findFallback(matches) {
643
+ // If only a single plugin matches, let's take that one
644
+ if (matches.length === 1) {
645
+ return matches[0];
646
+ }
647
+ // Otherwise, find the plugin that creates a valid rule given the arbitrary value, and
648
+ // also has the correct type which preferOnConflicts the plugin in case of clashes.
649
+ return matches.find((rules)=>{
650
+ let matchingTypes = typesByMatches.get(rules);
651
+ return rules.some(([{ options }, rule])=>{
652
+ if (!isParsableNode(rule)) {
653
+ return false;
654
+ }
655
+ return options.types.some(({ type , preferOnConflict })=>matchingTypes.includes(type) && preferOnConflict);
656
+ });
657
+ });
658
+ }
659
+ var ref2;
660
+ // Try to find a fallback plugin, because we already know that multiple plugins matched for
661
+ // the given arbitrary value.
662
+ let fallback = (ref2 = findFallback(withoutAny)) !== null && ref2 !== void 0 ? ref2 : findFallback(withAny);
663
+ if (fallback) {
664
+ matches = [
665
+ fallback
666
+ ];
667
+ } else {
668
+ var ref3;
669
+ let typesPerPlugin = matches.map((match)=>new Set([
670
+ ...(ref3 = typesByMatches.get(match)) !== null && ref3 !== void 0 ? ref3 : []
671
+ ]));
672
+ // Remove duplicates, so that we can detect proper unique types for each plugin.
673
+ for (let pluginTypes of typesPerPlugin){
674
+ for (let type of pluginTypes){
675
+ let removeFromOwnGroup = false;
676
+ for (let otherGroup of typesPerPlugin){
677
+ if (pluginTypes === otherGroup) continue;
678
+ if (otherGroup.has(type)) {
679
+ otherGroup.delete(type);
680
+ removeFromOwnGroup = true;
681
+ }
603
682
  }
683
+ if (removeFromOwnGroup) pluginTypes.delete(type);
604
684
  }
605
- if (removeFromOwnGroup) pluginTypes.delete(type);
606
685
  }
607
- }
608
- let messages = [];
609
- for (let [idx, group] of typesPerPlugin.entries()){
610
- for (let type1 of group){
611
- let rules2 = matches[idx].map(([, rule])=>rule).flat().map((rule)=>rule.toString().split("\n").slice(1, -1) // Remove selector and closing '}'
612
- .map((line)=>line.trim()).map((x)=>` ${x}`) // Re-indent
613
- .join("\n")).join("\n\n");
614
- messages.push(` Use \`${candidate.replace("[", `[${type1}:`)}\` for \`${rules2.trim()}\``);
615
- break;
686
+ let messages = [];
687
+ for (let [idx, group] of typesPerPlugin.entries()){
688
+ for (let type1 of group){
689
+ let rules2 = matches[idx].map(([, rule])=>rule).flat().map((rule)=>rule.toString().split("\n").slice(1, -1) // Remove selector and closing '}'
690
+ .map((line)=>line.trim()).map((x)=>` ${x}`) // Re-indent
691
+ .join("\n")).join("\n\n");
692
+ messages.push(` Use \`${candidate.replace("[", `[${type1}:`)}\` for \`${rules2.trim()}\``);
693
+ break;
694
+ }
616
695
  }
696
+ _log.default.warn([
697
+ `The class \`${candidate}\` is ambiguous and matches multiple utilities.`,
698
+ ...messages,
699
+ `If this is content and not a class, replace it with \`${candidate.replace("[", "&lsqb;").replace("]", "&rsqb;")}\` to silence this warning.`
700
+ ]);
701
+ continue;
617
702
  }
618
- _log.default.warn([
619
- `The class \`${candidate}\` is ambiguous and matches multiple utilities.`,
620
- ...messages,
621
- `If this is content and not a class, replace it with \`${candidate.replace("[", "&lsqb;").replace("]", "&rsqb;")}\` to silence this warning.`,
622
- ]);
623
- continue;
624
703
  }
625
704
  matches = matches.map((list)=>list.filter((match)=>isParsableNode(match[1])));
626
705
  }
@@ -667,14 +746,39 @@ function* resolveMatches(candidate, context, original = candidate) {
667
746
  function inKeyframes(rule) {
668
747
  return rule.parent && rule.parent.type === "atrule" && rule.parent.name === "keyframes";
669
748
  }
749
+ function getImportantStrategy(important) {
750
+ if (important === true) {
751
+ return (rule)=>{
752
+ if (inKeyframes(rule)) {
753
+ return;
754
+ }
755
+ rule.walkDecls((d)=>{
756
+ if (d.parent.type === "rule" && !inKeyframes(d.parent)) {
757
+ d.important = true;
758
+ }
759
+ });
760
+ };
761
+ }
762
+ if (typeof important === "string") {
763
+ return (rule)=>{
764
+ if (inKeyframes(rule)) {
765
+ return;
766
+ }
767
+ rule.selectors = rule.selectors.map((selector)=>{
768
+ return `${important} ${selector}`;
769
+ });
770
+ };
771
+ }
772
+ }
670
773
  function generateRules(candidates, context) {
671
774
  let allRules = [];
775
+ let strategy = getImportantStrategy(context.tailwindConfig.important);
672
776
  for (let candidate of candidates){
673
777
  if (context.notClassCache.has(candidate)) {
674
778
  continue;
675
779
  }
676
- if (context.classCache.has(candidate)) {
677
- allRules.push(context.classCache.get(candidate));
780
+ if (context.candidateRuleCache.has(candidate)) {
781
+ allRules = allRules.concat(Array.from(context.candidateRuleCache.get(candidate)));
678
782
  continue;
679
783
  }
680
784
  let matches = Array.from(resolveMatches(candidate, context));
@@ -683,49 +787,30 @@ function generateRules(candidates, context) {
683
787
  continue;
684
788
  }
685
789
  context.classCache.set(candidate, matches);
686
- allRules.push(matches);
687
- }
688
- // Strategy based on `tailwindConfig.important`
689
- let strategy = ((important)=>{
690
- if (important === true) {
691
- return (rule)=>{
692
- rule.walkDecls((d)=>{
693
- if (d.parent.type === "rule" && !inKeyframes(d.parent)) {
694
- d.important = true;
695
- }
696
- });
697
- };
698
- }
699
- if (typeof important === "string") {
700
- return (rule)=>{
701
- rule.selectors = rule.selectors.map((selector)=>{
702
- return `${important} ${selector}`;
703
- });
704
- };
705
- }
706
- })(context.tailwindConfig.important);
707
- return allRules.flat(1).map(([{ sort , layer , options }, rule])=>{
708
- if (options.respectImportant) {
709
- if (strategy) {
790
+ var ref;
791
+ let rules = (ref = context.candidateRuleCache.get(candidate)) !== null && ref !== void 0 ? ref : new Set();
792
+ context.candidateRuleCache.set(candidate, rules);
793
+ for (const match of matches){
794
+ let [{ sort , options }, rule] = match;
795
+ if (options.respectImportant && strategy) {
710
796
  let container = _postcss.default.root({
711
797
  nodes: [
712
798
  rule.clone()
713
799
  ]
714
800
  });
715
- container.walkRules((r)=>{
716
- if (inKeyframes(r)) {
717
- return;
718
- }
719
- strategy(r);
720
- });
801
+ container.walkRules(strategy);
721
802
  rule = container.nodes[0];
722
803
  }
804
+ let newEntry = [
805
+ sort,
806
+ rule
807
+ ];
808
+ rules.add(newEntry);
809
+ context.ruleCache.add(newEntry);
810
+ allRules.push(newEntry);
723
811
  }
724
- return [
725
- sort | context.layerOrder[layer],
726
- rule
727
- ];
728
- });
812
+ }
813
+ return allRules;
729
814
  }
730
815
  function isArbitraryValue(input) {
731
816
  return input.startsWith("[") && input.endsWith("]");
@@ -53,7 +53,7 @@ function normalizeTailwindDirectives(root) {
53
53
  _log.default.warn(`${atRule.name}-at-rule-deprecated`, [
54
54
  `The \`@${atRule.name}\` directive has been deprecated in Tailwind CSS v3.0.`,
55
55
  `Use \`@layer utilities\` or \`@layer components\` instead.`,
56
- "https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer",
56
+ "https://tailwindcss.com/docs/upgrade-guide#replace-variants-with-layer"
57
57
  ]);
58
58
  }
59
59
  layerDirectives.add(atRule);
@@ -0,0 +1,217 @@
1
+ // @ts-check
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "Offsets", {
7
+ enumerable: true,
8
+ get: ()=>Offsets
9
+ });
10
+ const _bigSign = /*#__PURE__*/ _interopRequireDefault(require("../util/bigSign"));
11
+ function _interopRequireDefault(obj) {
12
+ return obj && obj.__esModule ? obj : {
13
+ default: obj
14
+ };
15
+ }
16
+ class Offsets {
17
+ constructor(){
18
+ /**
19
+ * Offsets for the next rule in a given layer
20
+ *
21
+ * @type {Record<Layer, bigint>}
22
+ */ this.offsets = {
23
+ defaults: 0n,
24
+ base: 0n,
25
+ components: 0n,
26
+ utilities: 0n,
27
+ variants: 0n,
28
+ user: 0n
29
+ };
30
+ /**
31
+ * Positions for a given layer
32
+ *
33
+ * @type {Record<Layer, bigint>}
34
+ */ this.layerPositions = {
35
+ defaults: 0n,
36
+ base: 1n,
37
+ components: 2n,
38
+ utilities: 3n,
39
+ // There isn't technically a "user" layer, but we need to give it a position
40
+ // Because it's used for ordering user-css from @apply
41
+ user: 4n,
42
+ variants: 5n
43
+ };
44
+ /**
45
+ * The total number of functions currently registered across all variants (including arbitrary variants)
46
+ *
47
+ * @type {bigint}
48
+ */ this.reservedVariantBits = 0n;
49
+ /**
50
+ * Positions for a given variant
51
+ *
52
+ * @type {Map<string, bigint>}
53
+ */ this.variantOffsets = new Map();
54
+ }
55
+ /**
56
+ * @param {Layer} layer
57
+ * @returns {RuleOffset}
58
+ */ create(layer) {
59
+ return {
60
+ layer,
61
+ parentLayer: layer,
62
+ arbitrary: 0n,
63
+ variants: 0n,
64
+ parallelIndex: 0n,
65
+ index: this.offsets[layer]++,
66
+ options: []
67
+ };
68
+ }
69
+ /**
70
+ * @returns {RuleOffset}
71
+ */ arbitraryProperty() {
72
+ return {
73
+ ...this.create("utilities"),
74
+ arbitrary: 1n
75
+ };
76
+ }
77
+ /**
78
+ * Get the offset for a variant
79
+ *
80
+ * @param {string} variant
81
+ * @param {number} index
82
+ * @returns {RuleOffset}
83
+ */ forVariant(variant, index = 0) {
84
+ let offset = this.variantOffsets.get(variant);
85
+ if (offset === undefined) {
86
+ throw new Error(`Cannot find offset for unknown variant ${variant}`);
87
+ }
88
+ return {
89
+ ...this.create("variants"),
90
+ variants: offset << BigInt(index)
91
+ };
92
+ }
93
+ /**
94
+ * @param {RuleOffset} rule
95
+ * @param {RuleOffset} variant
96
+ * @param {VariantOption} options
97
+ * @returns {RuleOffset}
98
+ */ applyVariantOffset(rule, variant, options) {
99
+ return {
100
+ ...rule,
101
+ layer: "variants",
102
+ parentLayer: rule.layer === "variants" ? rule.parentLayer : rule.layer,
103
+ variants: rule.variants | variant.variants,
104
+ options: options.sort ? [].concat(options, rule.options) : rule.options,
105
+ // TODO: Technically this is wrong. We should be handling parallel index on a per variant basis.
106
+ // We'll take the max of all the parallel indexes for now.
107
+ // @ts-ignore
108
+ parallelIndex: max([
109
+ rule.parallelIndex,
110
+ variant.parallelIndex
111
+ ])
112
+ };
113
+ }
114
+ /**
115
+ * @param {RuleOffset} offset
116
+ * @param {number} parallelIndex
117
+ * @returns {RuleOffset}
118
+ */ applyParallelOffset(offset, parallelIndex) {
119
+ return {
120
+ ...offset,
121
+ parallelIndex: BigInt(parallelIndex)
122
+ };
123
+ }
124
+ /**
125
+ * Each variant gets 1 bit per function / rule registered.
126
+ * This is because multiple variants can be applied to a single rule and we need to know which ones are present and which ones are not.
127
+ * Additionally, every unique group of variants is grouped together in the stylesheet.
128
+ *
129
+ * This grouping is order-independent. For instance, we do not differentiate between `hover:focus` and `focus:hover`.
130
+ *
131
+ * @param {string[]} variants
132
+ * @param {(name: string) => number} getLength
133
+ */ recordVariants(variants, getLength) {
134
+ for (let variant of variants){
135
+ this.recordVariant(variant, getLength(variant));
136
+ }
137
+ }
138
+ /**
139
+ * The same as `recordVariants` but for a single arbitrary variant at runtime.
140
+ * @param {string} variant
141
+ * @param {number} fnCount
142
+ *
143
+ * @returns {RuleOffset} The highest offset for this variant
144
+ */ recordVariant(variant, fnCount = 1) {
145
+ this.variantOffsets.set(variant, 1n << this.reservedVariantBits);
146
+ // Ensure space is reserved for each "function" in the parallel variant
147
+ // by offsetting the next variant by the number of parallel variants
148
+ // in the one we just added.
149
+ // Single functions that return parallel variants are NOT handled separately here
150
+ // They're offset by 1 (or the number of functions) as usual
151
+ // And each rule returned is tracked separately since the functions are evaluated lazily.
152
+ // @see `RuleOffset.parallelIndex`
153
+ this.reservedVariantBits += BigInt(fnCount);
154
+ return {
155
+ ...this.create("variants"),
156
+ variants: 1n << this.reservedVariantBits
157
+ };
158
+ }
159
+ /**
160
+ * @param {RuleOffset} a
161
+ * @param {RuleOffset} b
162
+ * @returns {bigint}
163
+ */ compare(a, b) {
164
+ // Sort layers together
165
+ if (a.layer !== b.layer) {
166
+ return this.layerPositions[a.layer] - this.layerPositions[b.layer];
167
+ }
168
+ // Sort based on the sorting function
169
+ for (let aOptions of a.options){
170
+ for (let bOptions of b.options){
171
+ if (aOptions.id !== bOptions.id) continue;
172
+ if (!aOptions.sort || !bOptions.sort) continue;
173
+ let result = aOptions.sort({
174
+ value: aOptions.value,
175
+ modifier: aOptions.modifier
176
+ }, {
177
+ value: bOptions.value,
178
+ modifier: bOptions.modifier
179
+ });
180
+ if (result !== 0) return result;
181
+ }
182
+ }
183
+ // Sort variants in the order they were registered
184
+ if (a.variants !== b.variants) {
185
+ return a.variants - b.variants;
186
+ }
187
+ // Make sure each rule returned by a parallel variant is sorted in ascending order
188
+ if (a.parallelIndex !== b.parallelIndex) {
189
+ return a.parallelIndex - b.parallelIndex;
190
+ }
191
+ // Always sort arbitrary properties after other utilities
192
+ if (a.arbitrary !== b.arbitrary) {
193
+ return a.arbitrary - b.arbitrary;
194
+ }
195
+ // Sort utilities, components, etc… in the order they were registered
196
+ return a.index - b.index;
197
+ }
198
+ /**
199
+ * @template T
200
+ * @param {[RuleOffset, T][]} list
201
+ * @returns {[RuleOffset, T][]}
202
+ */ sort(list) {
203
+ return list.sort(([a], [b])=>(0, _bigSign.default)(this.compare(a, b)));
204
+ }
205
+ }
206
+ /**
207
+ *
208
+ * @param {bigint[]} nums
209
+ * @returns {bigint|null}
210
+ */ function max(nums) {
211
+ let max = null;
212
+ for (const num of nums){
213
+ max = max !== null && max !== void 0 ? max : num;
214
+ max = max > num ? max : num;
215
+ }
216
+ return max;
217
+ }
package/lib/lib/regex.js CHANGED
@@ -52,7 +52,7 @@ function nestedBrackets(open, close, depth = 1) {
52
52
  nestedBrackets(open, close, depth - 1)
53
53
  ]),
54
54
  /[^\s]*/,
55
- escape(close),
55
+ escape(close)
56
56
  ]);
57
57
  }
58
58
  function escape(string) {