tailwindcss 0.0.0-insiders.ea10bb9 → 0.0.0-insiders.ea4e1cd

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 (184) hide show
  1. package/README.md +1 -1
  2. package/lib/cli/build/deps.js +17 -9
  3. package/lib/cli/build/index.js +20 -10
  4. package/lib/cli/build/plugin.js +86 -70
  5. package/lib/cli/build/utils.js +18 -8
  6. package/lib/cli/build/watching.js +16 -12
  7. package/lib/cli/help/index.js +6 -4
  8. package/lib/cli/index.js +222 -10
  9. package/lib/cli/init/index.js +29 -12
  10. package/lib/cli-peer-dependencies.js +12 -4
  11. package/lib/cli.js +4 -226
  12. package/lib/corePluginList.js +7 -1
  13. package/lib/corePlugins.js +348 -75
  14. package/lib/css/preflight.css +2 -0
  15. package/lib/featureFlags.js +27 -15
  16. package/lib/index.js +1 -47
  17. package/lib/lib/cacheInvalidation.js +7 -5
  18. package/lib/lib/collapseAdjacentRules.js +5 -3
  19. package/lib/lib/collapseDuplicateDeclarations.js +12 -10
  20. package/lib/lib/content.js +34 -30
  21. package/lib/lib/defaultExtractor.js +15 -8
  22. package/lib/lib/detectNesting.js +10 -2
  23. package/lib/lib/evaluateTailwindFunctions.js +22 -20
  24. package/lib/lib/expandApplyAtRules.js +43 -35
  25. package/lib/lib/expandTailwindAtRules.js +46 -19
  26. package/lib/lib/findAtConfigPath.js +9 -7
  27. package/lib/lib/generateRules.js +157 -92
  28. package/lib/lib/getModuleDependencies.js +85 -37
  29. package/lib/lib/load-config.js +42 -0
  30. package/lib/lib/normalizeTailwindDirectives.js +5 -3
  31. package/lib/lib/offsets.js +93 -4
  32. package/lib/lib/partitionApplyAtRules.js +3 -1
  33. package/lib/lib/regex.js +21 -7
  34. package/lib/lib/remap-bitfield.js +89 -0
  35. package/lib/lib/resolveDefaultsAtRules.js +28 -24
  36. package/lib/lib/setupContextUtils.js +190 -131
  37. package/lib/lib/setupTrackingContext.js +49 -26
  38. package/lib/lib/sharedState.js +37 -10
  39. package/lib/lib/substituteScreenAtRules.js +5 -3
  40. package/lib/oxide/cli/build/deps.js +89 -0
  41. package/lib/oxide/cli/build/index.js +53 -0
  42. package/lib/oxide/cli/build/plugin.js +375 -0
  43. package/lib/oxide/cli/build/utils.js +87 -0
  44. package/lib/oxide/cli/build/watching.js +179 -0
  45. package/lib/oxide/cli/help/index.js +72 -0
  46. package/lib/oxide/cli/index.js +214 -0
  47. package/lib/oxide/cli/init/index.js +52 -0
  48. package/lib/oxide/cli.js +5 -0
  49. package/lib/oxide/postcss-plugin.js +2 -0
  50. package/lib/plugin.js +98 -0
  51. package/lib/postcss-plugins/nesting/index.js +3 -1
  52. package/lib/postcss-plugins/nesting/plugin.js +10 -8
  53. package/lib/processTailwindFeatures.js +14 -12
  54. package/lib/public/colors.js +49 -25
  55. package/lib/public/create-plugin.js +5 -3
  56. package/lib/public/default-config.js +6 -4
  57. package/lib/public/default-theme.js +6 -4
  58. package/lib/public/load-config.js +12 -0
  59. package/lib/public/resolve-config.js +6 -4
  60. package/lib/util/applyImportantSelector.js +36 -0
  61. package/lib/util/bigSign.js +3 -1
  62. package/lib/util/buildMediaQuery.js +3 -1
  63. package/lib/util/cloneDeep.js +3 -1
  64. package/lib/util/cloneNodes.js +5 -3
  65. package/lib/util/color.js +30 -12
  66. package/lib/util/colorNames.js +752 -0
  67. package/lib/util/configurePlugins.js +3 -1
  68. package/lib/util/createPlugin.js +3 -1
  69. package/lib/util/createUtilityPlugin.js +7 -5
  70. package/lib/util/dataTypes.js +74 -17
  71. package/lib/util/defaults.js +9 -7
  72. package/lib/util/escapeClassName.js +10 -8
  73. package/lib/util/escapeCommas.js +3 -1
  74. package/lib/util/flattenColorPalette.js +3 -1
  75. package/lib/util/formatVariantSelector.js +138 -160
  76. package/lib/util/getAllConfigs.js +8 -6
  77. package/lib/util/hashConfig.js +6 -4
  78. package/lib/util/isKeyframeRule.js +3 -1
  79. package/lib/util/isPlainObject.js +3 -1
  80. package/lib/util/isSyntacticallyValidPropertyValue.js +3 -1
  81. package/lib/util/log.js +8 -4
  82. package/lib/util/nameClass.js +12 -6
  83. package/lib/util/negateValue.js +4 -2
  84. package/lib/util/normalizeConfig.js +28 -27
  85. package/lib/util/normalizeScreens.js +12 -4
  86. package/lib/util/parseAnimationValue.js +3 -1
  87. package/lib/util/parseBoxShadowValue.js +6 -2
  88. package/lib/util/parseDependency.js +3 -1
  89. package/lib/util/parseGlob.js +6 -4
  90. package/lib/util/parseObjectStyles.js +9 -7
  91. package/lib/util/pluginUtils.js +54 -54
  92. package/lib/util/prefixSelector.js +27 -11
  93. package/lib/util/pseudoElements.js +229 -0
  94. package/lib/util/removeAlphaVariables.js +3 -1
  95. package/lib/util/resolveConfig.js +17 -15
  96. package/lib/util/resolveConfigPath.js +26 -10
  97. package/lib/util/responsive.js +6 -4
  98. package/lib/util/splitAtTopLevelOnly.js +10 -2
  99. package/lib/util/tap.js +3 -1
  100. package/lib/util/toColorValue.js +3 -1
  101. package/lib/util/toPath.js +3 -1
  102. package/lib/util/transformThemeValue.js +6 -4
  103. package/lib/util/validateConfig.js +16 -3
  104. package/lib/util/validateFormalSyntax.js +3 -1
  105. package/lib/util/withAlphaVariable.js +6 -2
  106. package/loadConfig.d.ts +4 -0
  107. package/loadConfig.js +2 -0
  108. package/package.json +45 -37
  109. package/peers/index.js +63324 -46417
  110. package/resolveConfig.d.ts +11 -2
  111. package/scripts/swap-engines.js +40 -0
  112. package/src/cli/build/index.js +13 -9
  113. package/src/cli/build/plugin.js +42 -32
  114. package/src/cli/build/watching.js +4 -2
  115. package/src/cli/index.js +216 -3
  116. package/src/cli/init/index.js +37 -8
  117. package/src/cli.js +4 -220
  118. package/src/corePluginList.js +1 -1
  119. package/src/corePlugins.js +207 -32
  120. package/src/css/preflight.css +2 -0
  121. package/src/featureFlags.js +6 -0
  122. package/src/index.js +1 -47
  123. package/src/lib/content.js +12 -17
  124. package/src/lib/defaultExtractor.js +9 -3
  125. package/src/lib/detectNesting.js +9 -1
  126. package/src/lib/expandApplyAtRules.js +8 -1
  127. package/src/lib/expandTailwindAtRules.js +36 -7
  128. package/src/lib/generateRules.js +124 -42
  129. package/src/lib/getModuleDependencies.js +70 -30
  130. package/src/lib/load-config.ts +31 -0
  131. package/src/lib/offsets.js +104 -1
  132. package/src/lib/remap-bitfield.js +82 -0
  133. package/src/lib/setupContextUtils.js +103 -54
  134. package/src/lib/setupTrackingContext.js +36 -11
  135. package/src/lib/sharedState.js +15 -4
  136. package/src/oxide/cli/build/deps.ts +91 -0
  137. package/src/oxide/cli/build/index.ts +47 -0
  138. package/src/oxide/cli/build/plugin.ts +442 -0
  139. package/src/oxide/cli/build/utils.ts +74 -0
  140. package/src/oxide/cli/build/watching.ts +225 -0
  141. package/src/oxide/cli/help/index.ts +69 -0
  142. package/src/oxide/cli/index.ts +204 -0
  143. package/src/oxide/cli/init/index.ts +59 -0
  144. package/src/oxide/cli.ts +1 -0
  145. package/src/oxide/postcss-plugin.ts +1 -0
  146. package/src/plugin.js +107 -0
  147. package/src/public/colors.js +22 -0
  148. package/src/public/default-config.js +1 -1
  149. package/src/public/default-theme.js +2 -2
  150. package/src/public/load-config.js +2 -0
  151. package/src/util/applyImportantSelector.js +27 -0
  152. package/src/util/color.js +18 -3
  153. package/src/util/colorNames.js +150 -0
  154. package/src/util/dataTypes.js +33 -4
  155. package/src/util/formatVariantSelector.js +160 -163
  156. package/src/util/getAllConfigs.js +2 -2
  157. package/src/util/negateValue.js +1 -1
  158. package/src/util/normalizeConfig.js +2 -1
  159. package/src/util/pluginUtils.js +16 -31
  160. package/src/util/prefixSelector.js +28 -10
  161. package/src/util/pseudoElements.js +170 -0
  162. package/src/util/resolveConfigPath.js +12 -1
  163. package/src/util/splitAtTopLevelOnly.js +8 -1
  164. package/src/util/validateConfig.js +13 -0
  165. package/stubs/.gitignore +1 -0
  166. package/stubs/.prettierrc.json +6 -0
  167. package/stubs/{defaultConfig.stub.js → config.full.js} +183 -146
  168. package/stubs/{simpleConfig.stub.js → config.simple.js} +0 -1
  169. package/stubs/postcss.config.js +6 -0
  170. package/stubs/tailwind.config.cjs +2 -0
  171. package/stubs/tailwind.config.js +2 -0
  172. package/stubs/tailwind.config.ts +3 -0
  173. package/types/config.d.ts +15 -9
  174. package/types/generated/colors.d.ts +22 -0
  175. package/types/generated/corePluginList.d.ts +1 -1
  176. package/types/generated/default-theme.d.ts +108 -79
  177. package/CHANGELOG.md +0 -2336
  178. package/lib/cli/shared.js +0 -12
  179. package/lib/constants.js +0 -44
  180. package/scripts/install-integrations.js +0 -27
  181. package/scripts/rebuildFixtures.js +0 -68
  182. package/src/cli/shared.js +0 -5
  183. package/src/constants.js +0 -17
  184. /package/stubs/{defaultPostCssConfig.stub.js → postcss.config.cjs} +0 -0
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  Object.defineProperty(exports, "default", {
6
6
  enumerable: true,
7
- get: ()=>_default
7
+ get: function() {
8
+ return _default;
9
+ }
8
10
  });
9
11
  function createPlugin(plugin, config) {
10
12
  return {
@@ -4,10 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  Object.defineProperty(exports, "default", {
6
6
  enumerable: true,
7
- get: ()=>createUtilityPlugin
7
+ get: function() {
8
+ return createUtilityPlugin;
9
+ }
8
10
  });
9
- const _transformThemeValue = /*#__PURE__*/ _interopRequireDefault(require("./transformThemeValue"));
10
- function _interopRequireDefault(obj) {
11
+ const _transformThemeValue = /*#__PURE__*/ _interop_require_default(require("./transformThemeValue"));
12
+ function _interop_require_default(obj) {
11
13
  return obj && obj.__esModule ? obj : {
12
14
  default: obj
13
15
  };
@@ -26,7 +28,7 @@ function createUtilityPlugin(themeKey, utilityVariations = [
26
28
  let group = Array.isArray(utilityVariation[0]) ? utilityVariation : [
27
29
  utilityVariation
28
30
  ];
29
- var ref;
31
+ var _theme;
30
32
  matchUtilities(group.reduce((obj, [classPrefix, properties])=>{
31
33
  return Object.assign(obj, {
32
34
  [classPrefix]: (value)=>{
@@ -44,7 +46,7 @@ function createUtilityPlugin(themeKey, utilityVariations = [
44
46
  });
45
47
  }, {}), {
46
48
  ...options,
47
- values: filterDefault ? Object.fromEntries(Object.entries((ref = theme(themeKey)) !== null && ref !== void 0 ? ref : {}).filter(([modifier])=>modifier !== "DEFAULT")) : theme(themeKey)
49
+ values: filterDefault ? Object.fromEntries(Object.entries((_theme = theme(themeKey)) !== null && _theme !== void 0 ? _theme : {}).filter(([modifier])=>modifier !== "DEFAULT")) : theme(themeKey)
48
50
  });
49
51
  }
50
52
  };
@@ -9,21 +9,51 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
- normalize: ()=>normalize,
13
- url: ()=>url,
14
- number: ()=>number,
15
- percentage: ()=>percentage,
16
- length: ()=>length,
17
- lineWidth: ()=>lineWidth,
18
- shadow: ()=>shadow,
19
- color: ()=>color,
20
- image: ()=>image,
21
- gradient: ()=>gradient,
22
- position: ()=>position,
23
- familyName: ()=>familyName,
24
- genericName: ()=>genericName,
25
- absoluteSize: ()=>absoluteSize,
26
- relativeSize: ()=>relativeSize
12
+ normalize: function() {
13
+ return normalize;
14
+ },
15
+ url: function() {
16
+ return url;
17
+ },
18
+ number: function() {
19
+ return number;
20
+ },
21
+ percentage: function() {
22
+ return percentage;
23
+ },
24
+ length: function() {
25
+ return length;
26
+ },
27
+ lineWidth: function() {
28
+ return lineWidth;
29
+ },
30
+ shadow: function() {
31
+ return shadow;
32
+ },
33
+ color: function() {
34
+ return color;
35
+ },
36
+ image: function() {
37
+ return image;
38
+ },
39
+ gradient: function() {
40
+ return gradient;
41
+ },
42
+ position: function() {
43
+ return position;
44
+ },
45
+ familyName: function() {
46
+ return familyName;
47
+ },
48
+ genericName: function() {
49
+ return genericName;
50
+ },
51
+ absoluteSize: function() {
52
+ return absoluteSize;
53
+ },
54
+ relativeSize: function() {
55
+ return relativeSize;
56
+ }
27
57
  });
28
58
  const _color = require("./color");
29
59
  const _parseBoxShadowValue = require("./parseBoxShadowValue");
@@ -38,7 +68,12 @@ let cssFunctions = [
38
68
  function isCSSFunction(value) {
39
69
  return cssFunctions.some((fn)=>new RegExp(`^${fn}\\(.*\\)`).test(value));
40
70
  }
71
+ const placeholder = "--tw-placeholder";
72
+ const placeholderRe = new RegExp(placeholder, "g");
41
73
  function normalize(value, isRoot = true) {
74
+ if (value.startsWith("--")) {
75
+ return `var(${value})`;
76
+ }
42
77
  // Keep raw strings if it starts with `url(`
43
78
  if (value.includes("url(")) {
44
79
  return value.split(/(url\(.*?\))/g).filter(Boolean).map((part)=>{
@@ -57,7 +92,11 @@ function normalize(value, isRoot = true) {
57
92
  // Add spaces around operators inside math functions like calc() that do not follow an operator
58
93
  // or '('.
59
94
  value = value.replace(/(calc|min|max|clamp)\(.+\)/g, (match)=>{
60
- return match.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, "$1 $2 ");
95
+ let vars = [];
96
+ return match.replace(/var\((--.+?)[,)]/g, (match, g1)=>{
97
+ vars.push(g1);
98
+ return match.replace(g1, placeholder);
99
+ }).replace(/(-?\d*\.?\d(?!\b-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, "$1 $2 ").replace(placeholderRe, ()=>vars.shift());
61
100
  });
62
101
  return value;
63
102
  }
@@ -70,6 +109,9 @@ function number(value) {
70
109
  function percentage(value) {
71
110
  return value.endsWith("%") && number(value.slice(0, -1)) || isCSSFunction(value);
72
111
  }
112
+ // Please refer to MDN when updating this list:
113
+ // https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_and_units
114
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries#container_query_length_units
73
115
  let lengthUnits = [
74
116
  "cm",
75
117
  "mm",
@@ -83,10 +125,25 @@ let lengthUnits = [
83
125
  "ch",
84
126
  "rem",
85
127
  "lh",
128
+ "rlh",
86
129
  "vw",
87
130
  "vh",
88
131
  "vmin",
89
- "vmax"
132
+ "vmax",
133
+ "vb",
134
+ "vi",
135
+ "svw",
136
+ "svh",
137
+ "lvw",
138
+ "lvh",
139
+ "dvw",
140
+ "dvh",
141
+ "cqw",
142
+ "cqh",
143
+ "cqi",
144
+ "cqb",
145
+ "cqmin",
146
+ "cqmax"
90
147
  ];
91
148
  let lengthUnitsPattern = `(?:${lengthUnits.join("|")})`;
92
149
  function length(value) {
@@ -4,20 +4,22 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  Object.defineProperty(exports, "defaults", {
6
6
  enumerable: true,
7
- get: ()=>defaults
7
+ get: function() {
8
+ return defaults;
9
+ }
8
10
  });
9
11
  function defaults(target, ...sources) {
10
12
  for (let source of sources){
11
13
  for(let k in source){
12
- var ref;
13
- if (!(target === null || target === void 0 ? void 0 : (ref = target.hasOwnProperty) === null || ref === void 0 ? void 0 : ref.call(target, k))) {
14
+ var _target_hasOwnProperty;
15
+ if (!(target === null || target === void 0 ? void 0 : (_target_hasOwnProperty = target.hasOwnProperty) === null || _target_hasOwnProperty === void 0 ? void 0 : _target_hasOwnProperty.call(target, k))) {
14
16
  target[k] = source[k];
15
17
  }
16
18
  }
17
- for (let k1 of Object.getOwnPropertySymbols(source)){
18
- var ref1;
19
- if (!(target === null || target === void 0 ? void 0 : (ref1 = target.hasOwnProperty) === null || ref1 === void 0 ? void 0 : ref1.call(target, k1))) {
20
- target[k1] = source[k1];
19
+ for (let k of Object.getOwnPropertySymbols(source)){
20
+ var _target_hasOwnProperty1;
21
+ if (!(target === null || target === void 0 ? void 0 : (_target_hasOwnProperty1 = target.hasOwnProperty) === null || _target_hasOwnProperty1 === void 0 ? void 0 : _target_hasOwnProperty1.call(target, k))) {
22
+ target[k] = source[k];
21
23
  }
22
24
  }
23
25
  }
@@ -4,19 +4,21 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  Object.defineProperty(exports, "default", {
6
6
  enumerable: true,
7
- get: ()=>escapeClassName
7
+ get: function() {
8
+ return escapeClassName;
9
+ }
8
10
  });
9
- const _postcssSelectorParser = /*#__PURE__*/ _interopRequireDefault(require("postcss-selector-parser"));
10
- const _escapeCommas = /*#__PURE__*/ _interopRequireDefault(require("./escapeCommas"));
11
- function _interopRequireDefault(obj) {
11
+ const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
12
+ const _escapeCommas = /*#__PURE__*/ _interop_require_default(require("./escapeCommas"));
13
+ function _interop_require_default(obj) {
12
14
  return obj && obj.__esModule ? obj : {
13
15
  default: obj
14
16
  };
15
17
  }
16
18
  function escapeClassName(className) {
17
- var ref;
18
- let node = _postcssSelectorParser.default.className();
19
+ var _node_raws;
20
+ let node = _postcssselectorparser.default.className();
19
21
  node.value = className;
20
- var ref1;
21
- return (0, _escapeCommas.default)((ref1 = node === null || node === void 0 ? void 0 : (ref = node.raws) === null || ref === void 0 ? void 0 : ref.value) !== null && ref1 !== void 0 ? ref1 : node.value);
22
+ var _node_raws_value;
23
+ return (0, _escapeCommas.default)((_node_raws_value = node === null || node === void 0 ? void 0 : (_node_raws = node.raws) === null || _node_raws === void 0 ? void 0 : _node_raws.value) !== null && _node_raws_value !== void 0 ? _node_raws_value : node.value);
22
24
  }
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  Object.defineProperty(exports, "default", {
6
6
  enumerable: true,
7
- get: ()=>escapeCommas
7
+ get: function() {
8
+ return escapeCommas;
9
+ }
8
10
  });
9
11
  function escapeCommas(className) {
10
12
  return className.replace(/\\,/g, "\\2c ");
@@ -4,7 +4,9 @@ Object.defineProperty(exports, "__esModule", {
4
4
  });
5
5
  Object.defineProperty(exports, "default", {
6
6
  enumerable: true,
7
- get: ()=>_default
7
+ get: function() {
8
+ return _default;
9
+ }
8
10
  });
9
11
  const flattenColorPalette = (colors)=>Object.assign({}, ...Object.entries(colors !== null && colors !== void 0 ? colors : {}).flatMap(([color, values])=>typeof values == "object" ? Object.entries(flattenColorPalette(values)).map(([number, hex])=>({
10
12
  [color + (number === "DEFAULT" ? "" : `-${number}`)]: hex
@@ -9,41 +9,62 @@ function _export(target, all) {
9
9
  });
10
10
  }
11
11
  _export(exports, {
12
- selectorFunctions: ()=>selectorFunctions,
13
- formatVariantSelector: ()=>formatVariantSelector,
14
- finalizeSelector: ()=>finalizeSelector
12
+ formatVariantSelector: function() {
13
+ return formatVariantSelector;
14
+ },
15
+ eliminateIrrelevantSelectors: function() {
16
+ return eliminateIrrelevantSelectors;
17
+ },
18
+ finalizeSelector: function() {
19
+ return finalizeSelector;
20
+ },
21
+ handleMergePseudo: function() {
22
+ return handleMergePseudo;
23
+ }
15
24
  });
16
- const _postcssSelectorParser = /*#__PURE__*/ _interopRequireDefault(require("postcss-selector-parser"));
17
- const _unesc = /*#__PURE__*/ _interopRequireDefault(require("postcss-selector-parser/dist/util/unesc"));
18
- const _escapeClassName = /*#__PURE__*/ _interopRequireDefault(require("../util/escapeClassName"));
19
- const _prefixSelector = /*#__PURE__*/ _interopRequireDefault(require("../util/prefixSelector"));
20
- function _interopRequireDefault(obj) {
25
+ const _postcssselectorparser = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser"));
26
+ const _unesc = /*#__PURE__*/ _interop_require_default(require("postcss-selector-parser/dist/util/unesc"));
27
+ const _escapeClassName = /*#__PURE__*/ _interop_require_default(require("../util/escapeClassName"));
28
+ const _prefixSelector = /*#__PURE__*/ _interop_require_default(require("../util/prefixSelector"));
29
+ const _pseudoElements = require("./pseudoElements");
30
+ function _interop_require_default(obj) {
21
31
  return obj && obj.__esModule ? obj : {
22
32
  default: obj
23
33
  };
24
34
  }
25
- var ref;
26
- let MERGE = ":merge";
27
- let PARENT = "&";
28
- let selectorFunctions = new Set([
29
- MERGE
30
- ]);
31
- function formatVariantSelector(current, ...others) {
32
- for (let other of others){
33
- let incomingValue = resolveFunctionArgument(other, MERGE);
34
- if (incomingValue !== null) {
35
- let existingValue = resolveFunctionArgument(current, MERGE, incomingValue);
36
- if (existingValue !== null) {
37
- let existingTarget = `${MERGE}(${incomingValue})`;
38
- let splitIdx = other.indexOf(existingTarget);
39
- let addition = other.slice(splitIdx + existingTarget.length).split(" ")[0];
40
- current = current.replace(existingTarget, existingTarget + addition);
41
- continue;
42
- }
43
- }
44
- current = other.replace(PARENT, current);
35
+ /** @typedef {import('postcss-selector-parser').Root} Root */ /** @typedef {import('postcss-selector-parser').Selector} Selector */ /** @typedef {import('postcss-selector-parser').Pseudo} Pseudo */ /** @typedef {import('postcss-selector-parser').Node} Node */ /** @typedef {{format: string, isArbitraryVariant: boolean}[]} RawFormats */ /** @typedef {import('postcss-selector-parser').Root} ParsedFormats */ /** @typedef {RawFormats | ParsedFormats} AcceptedFormats */ let MERGE = ":merge";
36
+ function formatVariantSelector(formats, { context , candidate }) {
37
+ var _context_tailwindConfig_prefix;
38
+ let prefix = (_context_tailwindConfig_prefix = context === null || context === void 0 ? void 0 : context.tailwindConfig.prefix) !== null && _context_tailwindConfig_prefix !== void 0 ? _context_tailwindConfig_prefix : "";
39
+ // Parse the format selector into an AST
40
+ let parsedFormats = formats.map((format)=>{
41
+ let ast = (0, _postcssselectorparser.default)().astSync(format.format);
42
+ return {
43
+ ...format,
44
+ ast: format.isArbitraryVariant ? ast : (0, _prefixSelector.default)(prefix, ast)
45
+ };
46
+ });
47
+ // We start with the candidate selector
48
+ let formatAst = _postcssselectorparser.default.root({
49
+ nodes: [
50
+ _postcssselectorparser.default.selector({
51
+ nodes: [
52
+ _postcssselectorparser.default.className({
53
+ value: (0, _escapeClassName.default)(candidate)
54
+ })
55
+ ]
56
+ })
57
+ ]
58
+ });
59
+ // And iteratively merge each format selector into the candidate selector
60
+ for (let { ast } of parsedFormats){
61
+ [formatAst, ast] = handleMergePseudo(formatAst, ast);
62
+ // 2. Merge the format selector into the current selector AST
63
+ ast.walkNesting((nesting)=>nesting.replaceWith(...formatAst.nodes[0].nodes));
64
+ // 3. Keep going!
65
+ formatAst = ast;
45
66
  }
46
- return current;
67
+ return formatAst;
47
68
  }
48
69
  /**
49
70
  * Given any node in a selector this gets the "simple" selector it's a part of
@@ -51,10 +72,10 @@ function formatVariantSelector(current, ...others) {
51
72
  * Technically :is(), :not(), :has(), etc… can have combinators but those are nested
52
73
  * inside the relevant node and won't be picked up so they're fine to ignore
53
74
  *
54
- * @param {import('postcss-selector-parser').Node} node
55
- * @returns {import('postcss-selector-parser').Node[]}
75
+ * @param {Node} node
76
+ * @returns {Node[]}
56
77
  **/ function simpleSelectorForNode(node) {
57
- /** @type {import('postcss-selector-parser').Node[]} */ let nodes = [];
78
+ /** @type {Node[]} */ let nodes = [];
58
79
  // Walk backwards until we hit a combinator node (or the start)
59
80
  while(node.prev() && node.prev().type !== "combinator"){
60
81
  node = node.prev();
@@ -70,8 +91,8 @@ function formatVariantSelector(current, ...others) {
70
91
  * Resorts the nodes in a selector to ensure they're in the correct order
71
92
  * Tags go before classes, and pseudo classes go after classes
72
93
  *
73
- * @param {import('postcss-selector-parser').Selector} sel
74
- * @returns {import('postcss-selector-parser').Selector}
94
+ * @param {Selector} sel
95
+ * @returns {Selector}
75
96
  **/ function resortSelector(sel) {
76
97
  sel.sort((a, b)=>{
77
98
  if (a.type === "tag" && b.type === "class") {
@@ -106,27 +127,20 @@ function eliminateIrrelevantSelectors(sel, base) {
106
127
  // meaning of the selector.
107
128
  // TODO: Can we do this for :matches, :is, and :where?
108
129
  }
109
- var ref1;
110
- function finalizeSelector(format, { selector , candidate , context , isArbitraryVariant , // Split by the separator, but ignore the separator inside square brackets:
111
- //
112
- // E.g.: dark:lg:hover:[paint-order:markers]
113
- // ┬ ┬ ┬ ┬
114
- // │ │ │ ╰── We will not split here
115
- // ╰──┴─────┴─────────────── We will split here
116
- //
117
- 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() }) {
118
- var ref2;
119
- let ast = (0, _postcssSelectorParser.default)().astSync(selector);
120
- // We explicitly DO NOT prefix classes in arbitrary variants
121
- if ((context === null || context === void 0 ? void 0 : (ref2 = context.tailwindConfig) === null || ref2 === void 0 ? void 0 : ref2.prefix) && !isArbitraryVariant) {
122
- format = (0, _prefixSelector.default)(context.tailwindConfig.prefix, format);
123
- }
124
- format = format.replace(PARENT, `.${(0, _escapeClassName.default)(candidate)}`);
125
- let formatAst = (0, _postcssSelectorParser.default)().astSync(format);
126
- // Remove extraneous selectors that do not include the base class/candidate being matched against
127
- // For example if we have a utility defined `.a, .b { color: red}`
128
- // And the formatted variant is sm:b then we want the final selector to be `.sm\:b` and not `.a, .sm\:b`
129
- ast.each((sel)=>eliminateIrrelevantSelectors(sel, base));
130
+ function finalizeSelector(current, formats, { context , candidate , base }) {
131
+ var _context_tailwindConfig;
132
+ var _context_tailwindConfig_separator;
133
+ let separator = (_context_tailwindConfig_separator = context === null || context === void 0 ? void 0 : (_context_tailwindConfig = context.tailwindConfig) === null || _context_tailwindConfig === void 0 ? void 0 : _context_tailwindConfig.separator) !== null && _context_tailwindConfig_separator !== void 0 ? _context_tailwindConfig_separator : ":";
134
+ // Split by the separator, but ignore the separator inside square brackets:
135
+ //
136
+ // E.g.: dark:lg:hover:[paint-order:markers]
137
+ // ┬ ┬ ┬ ┬
138
+ // │ │ │ ╰── We will not split here
139
+ // ╰──┴─────┴─────────────── We will split here
140
+ //
141
+ base = base !== null && base !== void 0 ? base : candidate.split(new RegExp(`\\${separator}(?![^[]*\\])`)).pop();
142
+ // Parse the selector into an AST
143
+ let selector = (0, _postcssselectorparser.default)().astSync(current);
130
144
  // Normalize escaped classes, e.g.:
131
145
  //
132
146
  // The idea would be to replace the escaped `base` in the selector with the
@@ -138,20 +152,31 @@ base =candidate.split(new RegExp(`\\${(ref1 = context === null || context === vo
138
152
  // base in selector: bg-\\[rgb\\(255\\,0\\,0\\)\\]
139
153
  // escaped base: bg-\\[rgb\\(255\\2c 0\\2c 0\\)\\]
140
154
  //
141
- ast.walkClasses((node)=>{
155
+ selector.walkClasses((node)=>{
142
156
  if (node.raws && node.value.includes(base)) {
143
157
  node.raws.value = (0, _escapeClassName.default)((0, _unesc.default)(node.raws.value));
144
158
  }
145
159
  });
146
- let simpleStart = _postcssSelectorParser.default.comment({
160
+ // Remove extraneous selectors that do not include the base candidate
161
+ selector.each((sel)=>eliminateIrrelevantSelectors(sel, base));
162
+ // If there are no formats that means there were no variants added to the candidate
163
+ // so we can just return the selector as-is
164
+ let formatAst = Array.isArray(formats) ? formatVariantSelector(formats, {
165
+ context,
166
+ candidate
167
+ }) : formats;
168
+ if (formatAst === null) {
169
+ return selector.toString();
170
+ }
171
+ let simpleStart = _postcssselectorparser.default.comment({
147
172
  value: "/*__simple__*/"
148
173
  });
149
- let simpleEnd = _postcssSelectorParser.default.comment({
174
+ let simpleEnd = _postcssselectorparser.default.comment({
150
175
  value: "/*__simple__*/"
151
176
  });
152
177
  // We can safely replace the escaped base now, since the `base` section is
153
178
  // now in a normalized escaped value.
154
- ast.walkClasses((node)=>{
179
+ selector.walkClasses((node)=>{
155
180
  if (node.value !== base) {
156
181
  return;
157
182
  }
@@ -166,120 +191,73 @@ base =candidate.split(new RegExp(`\\${(ref1 = context === null || context === vo
166
191
  parent.insertBefore(simpleSelector[0], simpleStart);
167
192
  parent.insertAfter(simpleSelector[simpleSelector.length - 1], simpleEnd);
168
193
  for (let child of formatNodes){
169
- parent.insertBefore(simpleSelector[0], child);
194
+ parent.insertBefore(simpleSelector[0], child.clone());
170
195
  }
171
196
  node.remove();
172
197
  // Re-sort the simple selector to ensure it's in the correct order
173
198
  simpleSelector = simpleSelectorForNode(simpleStart);
174
199
  let firstNode = parent.index(simpleStart);
175
- parent.nodes.splice(firstNode, simpleSelector.length, ...resortSelector(_postcssSelectorParser.default.selector({
200
+ parent.nodes.splice(firstNode, simpleSelector.length, ...resortSelector(_postcssselectorparser.default.selector({
176
201
  nodes: simpleSelector
177
202
  })).nodes);
178
203
  simpleStart.remove();
179
204
  simpleEnd.remove();
180
205
  });
181
- // This will make sure to move pseudo's to the correct spot (the end for
182
- // pseudo elements) because otherwise the selector will never work
183
- // anyway.
184
- //
185
- // E.g.:
186
- // - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
187
- // - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
188
- //
189
- // `::before:hover` doesn't work, which means that we can make it work for you by flipping the order.
190
- function collectPseudoElements(selector) {
191
- let nodes = [];
192
- for (let node of selector.nodes){
193
- if (isPseudoElement(node)) {
194
- nodes.push(node);
195
- selector.removeChild(node);
196
- }
197
- if (node === null || node === void 0 ? void 0 : node.nodes) {
198
- nodes.push(...collectPseudoElements(node));
199
- }
200
- }
201
- return nodes;
202
- }
203
206
  // Remove unnecessary pseudo selectors that we used as placeholders
204
- ast.each((selector)=>{
205
- selector.walkPseudos((p)=>{
206
- if (selectorFunctions.has(p.value)) {
207
- p.replaceWith(p.nodes);
208
- }
209
- });
210
- let pseudoElements = collectPseudoElements(selector);
211
- if (pseudoElements.length > 0) {
212
- selector.nodes.push(pseudoElements.sort(sortSelector));
207
+ selector.walkPseudos((p)=>{
208
+ if (p.value === MERGE) {
209
+ p.replaceWith(p.nodes);
213
210
  }
214
211
  });
215
- return ast.toString();
216
- }
217
- // Note: As a rule, double colons (::) should be used instead of a single colon
218
- // (:). This distinguishes pseudo-classes from pseudo-elements. However, since
219
- // this distinction was not present in older versions of the W3C spec, most
220
- // browsers support both syntaxes for the original pseudo-elements.
221
- let pseudoElementsBC = [
222
- ":before",
223
- ":after",
224
- ":first-line",
225
- ":first-letter"
226
- ];
227
- // These pseudo-elements _can_ be combined with other pseudo selectors AND the order does matter.
228
- let pseudoElementExceptions = [
229
- "::file-selector-button"
230
- ];
231
- // This will make sure to move pseudo's to the correct spot (the end for
232
- // pseudo elements) because otherwise the selector will never work
233
- // anyway.
234
- //
235
- // E.g.:
236
- // - `before:hover:text-center` would result in `.before\:hover\:text-center:hover::before`
237
- // - `hover:before:text-center` would result in `.hover\:before\:text-center:hover::before`
238
- //
239
- // `::before:hover` doesn't work, which means that we can make it work
240
- // for you by flipping the order.
241
- function sortSelector(a, z) {
242
- // Both nodes are non-pseudo's so we can safely ignore them and keep
243
- // them in the same order.
244
- if (a.type !== "pseudo" && z.type !== "pseudo") {
245
- return 0;
246
- }
247
- // If one of them is a combinator, we need to keep it in the same order
248
- // because that means it will start a new "section" in the selector.
249
- if (a.type === "combinator" ^ z.type === "combinator") {
250
- return 0;
251
- }
252
- // One of the items is a pseudo and the other one isn't. Let's move
253
- // the pseudo to the right.
254
- if (a.type === "pseudo" ^ z.type === "pseudo") {
255
- return (a.type === "pseudo") - (z.type === "pseudo");
256
- }
257
- // Both are pseudo's, move the pseudo elements (except for
258
- // ::file-selector-button) to the right.
259
- return isPseudoElement(a) - isPseudoElement(z);
260
- }
261
- function isPseudoElement(node) {
262
- if (node.type !== "pseudo") return false;
263
- if (pseudoElementExceptions.includes(node.value)) return false;
264
- return node.value.startsWith("::") || pseudoElementsBC.includes(node.value);
212
+ // Move pseudo elements to the end of the selector (if necessary)
213
+ selector.each((sel)=>(0, _pseudoElements.movePseudos)(sel));
214
+ return selector.toString();
265
215
  }
266
- function resolveFunctionArgument(haystack, needle, arg) {
267
- let startIdx = haystack.indexOf(arg ? `${needle}(${arg})` : needle);
268
- if (startIdx === -1) return null;
269
- // Start inside the `(`
270
- startIdx += needle.length + 1;
271
- let target = "";
272
- let count = 0;
273
- for (let char of haystack.slice(startIdx)){
274
- if (char !== "(" && char !== ")") {
275
- target += char;
276
- } else if (char === "(") {
277
- target += char;
278
- count++;
279
- } else if (char === ")") {
280
- if (--count < 0) break; // unbalanced
281
- target += char;
216
+ function handleMergePseudo(selector, format) {
217
+ /** @type {{pseudo: Pseudo, value: string}[]} */ let merges = [];
218
+ // Find all :merge() pseudo-classes in `selector`
219
+ selector.walkPseudos((pseudo)=>{
220
+ if (pseudo.value === MERGE) {
221
+ merges.push({
222
+ pseudo,
223
+ value: pseudo.nodes[0].toString()
224
+ });
282
225
  }
283
- }
284
- return target;
226
+ });
227
+ // Find all :merge() "attachments" in `format` and attach them to the matching selector in `selector`
228
+ format.walkPseudos((pseudo)=>{
229
+ if (pseudo.value !== MERGE) {
230
+ return;
231
+ }
232
+ let value = pseudo.nodes[0].toString();
233
+ // Does `selector` contain a :merge() pseudo-class with the same value?
234
+ let existing = merges.find((merge)=>merge.value === value);
235
+ // Nope so there's nothing to do
236
+ if (!existing) {
237
+ return;
238
+ }
239
+ // Everything after `:merge()` up to the next combinator is what is attached to the merged selector
240
+ let attachments = [];
241
+ let next = pseudo.next();
242
+ while(next && next.type !== "combinator"){
243
+ attachments.push(next);
244
+ next = next.next();
245
+ }
246
+ let combinator = next;
247
+ existing.pseudo.parent.insertAfter(existing.pseudo, _postcssselectorparser.default.selector({
248
+ nodes: attachments.map((node)=>node.clone())
249
+ }));
250
+ pseudo.remove();
251
+ attachments.forEach((node)=>node.remove());
252
+ // What about this case:
253
+ // :merge(.group):focus > &
254
+ // :merge(.group):hover &
255
+ if (combinator && combinator.type === "combinator") {
256
+ combinator.remove();
257
+ }
258
+ });
259
+ return [
260
+ selector,
261
+ format
262
+ ];
285
263
  }