tailwindcss 3.1.8 → 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 +6 -5
  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 +66 -37
  21. package/lib/lib/expandTailwindAtRules.js +10 -42
  22. package/lib/lib/findAtConfigPath.js +44 -0
  23. package/lib/lib/generateRules.js +180 -93
  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 +2 -2
  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 +13 -11
  53. package/peers/.DS_Store +0 -0
  54. package/peers/.svgo.yml +75 -0
  55. package/peers/index.js +3332 -2032
  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 +70 -29
  81. package/src/lib/expandTailwindAtRules.js +8 -46
  82. package/src/lib/findAtConfigPath.js +48 -0
  83. package/src/lib/generateRules.js +223 -101
  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 +1 -1
  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 -2231
@@ -358,3 +358,8 @@ video {
358
358
  max-width: 100%;
359
359
  height: auto;
360
360
  }
361
+
362
+ /* Make elements with the HTML hidden attribute stay hidden by default */
363
+ [hidden] {
364
+ display: none;
365
+ }
@@ -21,16 +21,19 @@ function _interopRequireDefault(obj) {
21
21
  };
22
22
  }
23
23
  let defaults = {
24
- optimizeUniversalDefaults: false
24
+ optimizeUniversalDefaults: false,
25
+ generalizedModifiers: true
25
26
  };
26
27
  let featureFlags = {
27
28
  future: [
28
29
  "hoverOnlyWhenSupported",
29
- "respectDefaultRingColorOpacity"
30
+ "respectDefaultRingColorOpacity",
31
+ "disableColorOpacityUtilitiesByDefault",
32
+ "relativeContentPathsByDefault"
30
33
  ],
31
34
  experimental: [
32
35
  "optimizeUniversalDefaults",
33
- "matchVariant" /* , 'variantGrouping' */
36
+ "generalizedModifiers"
34
37
  ]
35
38
  };
36
39
  function flagEnabled(config, flag) {
@@ -61,7 +64,7 @@ function issueFlagNotices(config) {
61
64
  let changes = experimentalFlagsEnabled(config).map((s)=>_picocolors.default.yellow(s)).join(", ");
62
65
  _log.default.warn("experimental-flags-enabled", [
63
66
  `You have enabled experimental features: ${changes}`,
64
- "Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time.",
67
+ "Experimental features in Tailwind CSS are not covered by semver, may introduce breaking changes, and can change at any time."
65
68
  ]);
66
69
  }
67
70
  }
package/lib/index.js CHANGED
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  const _setupTrackingContext = /*#__PURE__*/ _interopRequireDefault(require("./lib/setupTrackingContext"));
6
6
  const _processTailwindFeatures = /*#__PURE__*/ _interopRequireDefault(require("./processTailwindFeatures"));
7
7
  const _sharedState = require("./lib/sharedState");
8
+ const _findAtConfigPath = require("./lib/findAtConfigPath");
8
9
  function _interopRequireDefault(obj) {
9
10
  return obj && obj.__esModule ? obj : {
10
11
  default: obj
@@ -20,6 +21,10 @@ module.exports = function tailwindcss(configOrPath) {
20
21
  return root;
21
22
  },
22
23
  function(root, result) {
24
+ var ref;
25
+ // Use the path for the `@config` directive if it exists, otherwise use the
26
+ // path for the file being processed
27
+ configOrPath = (ref = (0, _findAtConfigPath.findAtConfigPath)(root, result)) !== null && ref !== void 0 ? ref : configOrPath;
23
28
  let context = (0, _setupTrackingContext.default)(configOrPath);
24
29
  if (root.type === "document") {
25
30
  let roots = root.nodes.filter((node)=>node.type === "root");
@@ -36,7 +41,7 @@ module.exports = function tailwindcss(configOrPath) {
36
41
  console.timeEnd("JIT TOTAL");
37
42
  console.log("\n");
38
43
  return root;
39
- },
44
+ }
40
45
  ].filter(Boolean)
41
46
  };
42
47
  };
@@ -0,0 +1,167 @@
1
+ // @ts-check
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ function _export(target, all) {
7
+ for(var name in all)Object.defineProperty(target, name, {
8
+ enumerable: true,
9
+ get: all[name]
10
+ });
11
+ }
12
+ _export(exports, {
13
+ parseCandidateFiles: ()=>parseCandidateFiles,
14
+ resolvedChangedContent: ()=>resolvedChangedContent
15
+ });
16
+ const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
17
+ const _path = /*#__PURE__*/ _interopRequireDefault(require("path"));
18
+ const _isGlob = /*#__PURE__*/ _interopRequireDefault(require("is-glob"));
19
+ const _fastGlob = /*#__PURE__*/ _interopRequireDefault(require("fast-glob"));
20
+ const _normalizePath = /*#__PURE__*/ _interopRequireDefault(require("normalize-path"));
21
+ const _parseGlob = require("../util/parseGlob");
22
+ const _sharedState = require("./sharedState");
23
+ function _interopRequireDefault(obj) {
24
+ return obj && obj.__esModule ? obj : {
25
+ default: obj
26
+ };
27
+ }
28
+ function parseCandidateFiles(context, tailwindConfig) {
29
+ let files = tailwindConfig.content.files;
30
+ // Normalize the file globs
31
+ files = files.filter((filePath)=>typeof filePath === "string");
32
+ files = files.map(_normalizePath.default);
33
+ // Split into included and excluded globs
34
+ let tasks = _fastGlob.default.generateTasks(files);
35
+ /** @type {ContentPath[]} */ let included = [];
36
+ /** @type {ContentPath[]} */ let excluded = [];
37
+ for (const task of tasks){
38
+ included.push(...task.positive.map((filePath)=>parseFilePath(filePath, false)));
39
+ excluded.push(...task.negative.map((filePath)=>parseFilePath(filePath, true)));
40
+ }
41
+ let paths = [
42
+ ...included,
43
+ ...excluded
44
+ ];
45
+ // Resolve paths relative to the config file or cwd
46
+ paths = resolveRelativePaths(context, paths);
47
+ // Resolve symlinks if possible
48
+ paths = paths.flatMap(resolvePathSymlinks);
49
+ // Update cached patterns
50
+ paths = paths.map(resolveGlobPattern);
51
+ return paths;
52
+ }
53
+ /**
54
+ *
55
+ * @param {string} filePath
56
+ * @param {boolean} ignore
57
+ * @returns {ContentPath}
58
+ */ function parseFilePath(filePath, ignore) {
59
+ let contentPath = {
60
+ original: filePath,
61
+ base: filePath,
62
+ ignore,
63
+ pattern: filePath,
64
+ glob: null
65
+ };
66
+ if ((0, _isGlob.default)(filePath)) {
67
+ Object.assign(contentPath, (0, _parseGlob.parseGlob)(filePath));
68
+ }
69
+ return contentPath;
70
+ }
71
+ /**
72
+ *
73
+ * @param {ContentPath} contentPath
74
+ * @returns {ContentPath}
75
+ */ function resolveGlobPattern(contentPath) {
76
+ contentPath.pattern = contentPath.glob ? `${contentPath.base}/${contentPath.glob}` : contentPath.base;
77
+ contentPath.pattern = contentPath.ignore ? `!${contentPath.pattern}` : contentPath.pattern;
78
+ // This is required for Windows support to properly pick up Glob paths.
79
+ // Afaik, this technically shouldn't be needed but there's probably
80
+ // some internal, direct path matching with a normalized path in
81
+ // a package which can't handle mixed directory separators
82
+ contentPath.pattern = (0, _normalizePath.default)(contentPath.pattern);
83
+ return contentPath;
84
+ }
85
+ /**
86
+ * Resolve each path relative to the config file (when possible) if the experimental flag is enabled
87
+ * Otherwise, resolve relative to the current working directory
88
+ *
89
+ * @param {any} context
90
+ * @param {ContentPath[]} contentPaths
91
+ * @returns {ContentPath[]}
92
+ */ function resolveRelativePaths(context, contentPaths) {
93
+ let resolveFrom = [];
94
+ // Resolve base paths relative to the config file (when possible) if the experimental flag is enabled
95
+ if (context.userConfigPath && context.tailwindConfig.content.relative) {
96
+ resolveFrom = [
97
+ _path.default.dirname(context.userConfigPath)
98
+ ];
99
+ }
100
+ return contentPaths.map((contentPath)=>{
101
+ contentPath.base = _path.default.resolve(...resolveFrom, contentPath.base);
102
+ return contentPath;
103
+ });
104
+ }
105
+ /**
106
+ * Resolve the symlink for the base directory / file in each path
107
+ * These are added as additional dependencies to watch for changes because
108
+ * some tools (like webpack) will only watch the actual file or directory
109
+ * but not the symlink itself even in projects that use monorepos.
110
+ *
111
+ * @param {ContentPath} contentPath
112
+ * @returns {ContentPath[]}
113
+ */ function resolvePathSymlinks(contentPath) {
114
+ let paths = [
115
+ contentPath
116
+ ];
117
+ try {
118
+ let resolvedPath = _fs.default.realpathSync(contentPath.base);
119
+ if (resolvedPath !== contentPath.base) {
120
+ paths.push({
121
+ ...contentPath,
122
+ base: resolvedPath
123
+ });
124
+ }
125
+ } catch {
126
+ // TODO: log this?
127
+ }
128
+ return paths;
129
+ }
130
+ function resolvedChangedContent(context, candidateFiles, fileModifiedMap) {
131
+ let changedContent = context.tailwindConfig.content.files.filter((item)=>typeof item.raw === "string").map(({ raw , extension ="html" })=>({
132
+ content: raw,
133
+ extension
134
+ }));
135
+ for (let changedFile of resolveChangedFiles(candidateFiles, fileModifiedMap)){
136
+ let content = _fs.default.readFileSync(changedFile, "utf8");
137
+ let extension = _path.default.extname(changedFile).slice(1);
138
+ changedContent.push({
139
+ content,
140
+ extension
141
+ });
142
+ }
143
+ return changedContent;
144
+ }
145
+ /**
146
+ *
147
+ * @param {ContentPath[]} candidateFiles
148
+ * @param {Map<string, number>} fileModifiedMap
149
+ * @returns {Set<string>}
150
+ */ function resolveChangedFiles(candidateFiles, fileModifiedMap) {
151
+ let paths = candidateFiles.map((contentPath)=>contentPath.pattern);
152
+ let changedFiles = new Set();
153
+ _sharedState.env.DEBUG && console.time("Finding changed files");
154
+ let files = _fastGlob.default.sync(paths, {
155
+ absolute: true
156
+ });
157
+ for (let file of files){
158
+ let prevModified = fileModifiedMap.has(file) ? fileModifiedMap.get(file) : -Infinity;
159
+ let modified = _fs.default.statSync(file).mtimeMs;
160
+ if (modified > prevModified) {
161
+ changedFiles.add(file);
162
+ fileModifiedMap.set(file, modified);
163
+ }
164
+ }
165
+ _sharedState.env.DEBUG && console.timeEnd("Finding changed files");
166
+ return changedFiles;
167
+ }
@@ -85,7 +85,7 @@ function* buildRegExps(context) {
85
85
  // Not immediately followed by an `{[(`
86
86
  /(?![{([]])/,
87
87
  // optionally followed by an opacity modifier
88
- /(?:\/[^\s'"`\\><$]*)?/,
88
+ /(?:\/[^\s'"`\\><$]*)?/
89
89
  ]),
90
90
  _regex.pattern([
91
91
  // Arbitrary values
@@ -93,16 +93,21 @@ function* buildRegExps(context) {
93
93
  // Not immediately followed by an `{[(`
94
94
  /(?![{([]])/,
95
95
  // optionally followed by an opacity modifier
96
- /(?:\/[^\s'"`\\$]*)?/,
96
+ /(?:\/[^\s'"`\\$]*)?/
97
97
  ]),
98
98
  // Normal values w/o quotes — may include an opacity modifier
99
- /[-\/][^\s'"`\\$={><]*/,
100
- ])),
101
- ]),
99
+ /[-\/][^\s'"`\\$={><]*/
100
+ ]))
101
+ ])
102
102
  ]);
103
103
  let variantPatterns = [
104
104
  // Without quotes
105
105
  _regex.any([
106
+ // This is here to provide special support for the `@` variant
107
+ _regex.pattern([
108
+ /@\[[^\s"'`]+\](\/[^\s"'`]+)?/,
109
+ separator
110
+ ]),
106
111
  _regex.pattern([
107
112
  /([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/,
108
113
  separator
@@ -110,7 +115,7 @@ function* buildRegExps(context) {
110
115
  _regex.pattern([
111
116
  /[^\s"'`\[\\]+/,
112
117
  separator
113
- ]),
118
+ ])
114
119
  ]),
115
120
  // With quotes allowed
116
121
  _regex.any([
@@ -121,8 +126,8 @@ function* buildRegExps(context) {
121
126
  _regex.pattern([
122
127
  /[^\s`\[\\]+/,
123
128
  separator
124
- ]),
125
- ]),
129
+ ])
130
+ ])
126
131
  ];
127
132
  for (const variantPattern of variantPatterns){
128
133
  yield _regex.pattern([
@@ -145,8 +150,8 @@ function* buildRegExps(context) {
145
150
  /\)/
146
151
  ]),
147
152
  // Arbitrary properties, constrained utilities, arbitrary values, etc…
148
- utility,
149
- ]) : utility,
153
+ utility
154
+ ]) : utility
150
155
  ]);
151
156
  }
152
157
  // 5. Inner matches
@@ -16,7 +16,7 @@ function _default(_context) {
16
16
  node.warn(result, [
17
17
  "Nested @tailwind rules were detected, but are not supported.",
18
18
  "Consider using a prefix to scope Tailwind's classes: https://tailwindcss.com/docs/configuration#prefix",
19
- "Alternatively, use the important selector strategy: https://tailwindcss.com/docs/configuration#selector-strategy",
19
+ "Alternatively, use the important selector strategy: https://tailwindcss.com/docs/configuration#selector-strategy"
20
20
  ].join("\n"));
21
21
  return false;
22
22
  }
@@ -28,7 +28,7 @@ function _default(_context) {
28
28
  nestedRule.warn(result, [
29
29
  "Nested CSS was detected, but CSS nesting has not been configured correctly.",
30
30
  "Please enable a CSS nesting plugin *before* Tailwind in your configuration.",
31
- "See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting",
31
+ "See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting"
32
32
  ].join("\n"));
33
33
  return false;
34
34
  });
@@ -15,6 +15,7 @@ const _buildMediaQuery = /*#__PURE__*/ _interopRequireDefault(require("../util/b
15
15
  const _toPath = require("../util/toPath");
16
16
  const _withAlphaVariable = require("../util/withAlphaVariable");
17
17
  const _pluginUtils = require("../util/pluginUtils");
18
+ const _log = /*#__PURE__*/ _interopRequireDefault(require("../util/log"));
18
19
  function _interopRequireDefault(obj) {
19
20
  return obj && obj.__esModule ? obj : {
20
21
  default: obj
@@ -179,11 +180,26 @@ let nodeTypePropertyMap = {
179
180
  var ref;
180
181
  return (ref = results.find((result)=>result.isValid)) !== null && ref !== void 0 ? ref : results[0];
181
182
  }
182
- function _default({ tailwindConfig: config }) {
183
+ function _default(context) {
184
+ let config = context.tailwindConfig;
183
185
  let functions = {
184
186
  theme: (node, path, ...defaultValue)=>{
185
187
  let { isValid , value , error , alpha } = resolvePath(config, path, defaultValue.length ? defaultValue : undefined);
186
188
  if (!isValid) {
189
+ var ref;
190
+ let parentNode = node.parent;
191
+ let candidate = (ref = parentNode === null || parentNode === void 0 ? void 0 : parentNode.raws.tailwind) === null || ref === void 0 ? void 0 : ref.candidate;
192
+ if (parentNode && candidate !== undefined) {
193
+ // Remove this utility from any caches
194
+ context.markInvalidUtilityNode(parentNode);
195
+ // Remove the CSS node from the markup
196
+ parentNode.remove();
197
+ // Show a warning
198
+ _log.default.warn("invalid-theme-key-in-class", [
199
+ `The utility \`${candidate}\` contains an invalid theme value and was not generated.`
200
+ ]);
201
+ return;
202
+ }
187
203
  throw node.error(error);
188
204
  }
189
205
  let maybeColor = (0, _pluginUtils.parseColorFormat)(value);
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "default", {
9
9
  const _postcss = /*#__PURE__*/ _interopRequireDefault(require("postcss"));
10
10
  const _postcssSelectorParser = /*#__PURE__*/ _interopRequireDefault(require("postcss-selector-parser"));
11
11
  const _generateRules = require("./generateRules");
12
- const _bigSign = /*#__PURE__*/ _interopRequireDefault(require("../util/bigSign"));
13
12
  const _escapeClassName = /*#__PURE__*/ _interopRequireDefault(require("../util/escapeClassName"));
14
13
  function _interopRequireDefault(obj) {
15
14
  return obj && obj.__esModule ? obj : {
@@ -41,11 +40,11 @@ function _interopRequireDefault(obj) {
41
40
  groups: normalizedGroups
42
41
  });
43
42
  }
44
- let selectorExtractor = (0, _postcssSelectorParser.default)((root)=>root.nodes.map((node)=>node.toString()));
43
+ let selectorExtractor = (0, _postcssSelectorParser.default)();
45
44
  /**
46
45
  * @param {string} ruleSelectors
47
46
  */ function extractSelectors(ruleSelectors) {
48
- return selectorExtractor.transformSync(ruleSelectors);
47
+ return selectorExtractor.astSync(ruleSelectors);
49
48
  }
50
49
  function extractBaseCandidates(candidates, separator) {
51
50
  let baseClasses = new Set();
@@ -137,8 +136,7 @@ function* pathToRoot(node) {
137
136
  * @param {import('postcss').Root} root
138
137
  */ function buildLocalApplyCache(root, context) {
139
138
  /** @type {ApplyCache} */ let cache = new Map();
140
- let highestOffset = context.layerOrder.user >> 4n;
141
- root.walkRules((rule, idx)=>{
139
+ root.walkRules((rule)=>{
142
140
  // Ignore rules generated by Tailwind
143
141
  for (let node of pathToRoot(rule)){
144
142
  var ref;
@@ -148,16 +146,17 @@ function* pathToRoot(node) {
148
146
  }
149
147
  // Clone what's required to represent this singular rule in the tree
150
148
  let container = nestedClone(rule);
149
+ let sort = context.offsets.create("user");
151
150
  for (let className of extractClasses(rule)){
152
151
  let list = cache.get(className) || [];
153
152
  cache.set(className, list);
154
153
  list.push([
155
154
  {
156
155
  layer: "user",
157
- sort: BigInt(idx) + highestOffset,
156
+ sort,
158
157
  important: false
159
158
  },
160
- container,
159
+ container
161
160
  ]);
162
161
  }
163
162
  });
@@ -268,30 +267,64 @@ function processApply(root, context, localCache) {
268
267
  * What happens in this function is that we prepend a `.` and escape the candidate.
269
268
  * This will result in `.hover\:font-bold`
270
269
  * Which means that we can replace `.hover\:font-bold` with `.abc` in `.hover\:font-bold:hover` resulting in `.abc:hover`
271
- */ // TODO: Should we use postcss-selector-parser for this instead?
272
- function replaceSelector(selector, utilitySelectors, candidate) {
273
- let needle = `.${(0, _escapeClassName.default)(candidate)}`;
274
- let needles = [
275
- ...new Set([
276
- needle,
277
- needle.replace(/\\2c /g, "\\,")
278
- ])
279
- ];
270
+ *
271
+ * @param {string} selector
272
+ * @param {string} utilitySelectors
273
+ * @param {string} candidate
274
+ */ function replaceSelector(selector, utilitySelectors, candidate) {
275
+ let selectorList = extractSelectors(selector);
280
276
  let utilitySelectorsList = extractSelectors(utilitySelectors);
281
- return extractSelectors(selector).map((s)=>{
282
- let replaced = [];
283
- for (let utilitySelector of utilitySelectorsList){
284
- let replacedSelector = utilitySelector;
285
- for (const needle of needles){
286
- replacedSelector = replacedSelector.replace(needle, s);
287
- }
288
- if (replacedSelector === utilitySelector) {
289
- continue;
290
- }
291
- replaced.push(replacedSelector);
277
+ let candidateList = extractSelectors(`.${(0, _escapeClassName.default)(candidate)}`);
278
+ let candidateClass = candidateList.nodes[0].nodes[0];
279
+ selectorList.each((sel)=>{
280
+ /** @type {Set<import('postcss-selector-parser').Selector>} */ let replaced = new Set();
281
+ utilitySelectorsList.each((utilitySelector)=>{
282
+ let hasReplaced = false;
283
+ utilitySelector = utilitySelector.clone();
284
+ utilitySelector.walkClasses((node)=>{
285
+ if (node.value !== candidateClass.value) {
286
+ return;
287
+ }
288
+ // Don't replace multiple instances of the same class
289
+ // This is theoretically correct but only partially
290
+ // We'd need to generate every possible permutation of the replacement
291
+ // For example with `.foo + .foo { … }` and `section { @apply foo; }`
292
+ // We'd need to generate all of these:
293
+ // - `.foo + .foo`
294
+ // - `.foo + section`
295
+ // - `section + .foo`
296
+ // - `section + section`
297
+ if (hasReplaced) {
298
+ return;
299
+ }
300
+ // Since you can only `@apply` class names this is sufficient
301
+ // We want to replace the matched class name with the selector the user is using
302
+ // Ex: Replace `.text-blue-500` with `.foo.bar:is(.something-cool)`
303
+ node.replaceWith(...sel.nodes.map((node)=>node.clone()));
304
+ // Record that we did something and we want to use this new selector
305
+ replaced.add(utilitySelector);
306
+ hasReplaced = true;
307
+ });
308
+ });
309
+ // Sort tag names before class names
310
+ // This happens when replacing `.bar` in `.foo.bar` with a tag like `section`
311
+ for (const sel1 of replaced){
312
+ sel1.sort((a, b)=>{
313
+ if (a.type === "tag" && b.type === "class") {
314
+ return -1;
315
+ } else if (a.type === "class" && b.type === "tag") {
316
+ return 1;
317
+ } else if (a.type === "class" && b.type === "pseudo") {
318
+ return -1;
319
+ } else if (a.type === "pseudo" && b.type === "class") {
320
+ return 1;
321
+ }
322
+ return sel1.index(a) - sel1.index(b);
323
+ });
292
324
  }
293
- return replaced.join(", ");
294
- }).join(", ");
325
+ sel.replaceWith(...replaced);
326
+ });
327
+ return selectorList.toString();
295
328
  }
296
329
  let perParentApplies = new Map();
297
330
  // Collect all apply candidates and their rules
@@ -338,7 +371,7 @@ function processApply(root, context, localCache) {
338
371
  applyCandidate1,
339
372
  ...extractBaseCandidates([
340
373
  applyCandidate1
341
- ], context.tailwindConfig.separator),
374
+ ], context.tailwindConfig.separator)
342
375
  ];
343
376
  for (let [meta, node] of rules1){
344
377
  let parentClasses = extractClasses(parent);
@@ -443,17 +476,13 @@ function processApply(root, context, localCache) {
443
476
  }
444
477
  // Insert it
445
478
  siblings.push([
446
- // Ensure that when we are sorting, that we take the layer order into account
447
- {
448
- ...meta,
449
- sort: meta.sort | context.layerOrder[meta.layer]
450
- },
451
- root1.nodes[0],
479
+ meta.sort,
480
+ root1.nodes[0]
452
481
  ]);
453
482
  }
454
483
  }
455
484
  // Inject the rules, sorted, correctly
456
- let nodes = siblings.sort(([a], [z])=>(0, _bigSign.default)(a.sort - z.sort)).map((s)=>s[1]);
485
+ let nodes = context.offsets.sort(siblings).map((s)=>s[1]);
457
486
  // `parent` refers to the node at `.abc` in: .abc { @apply mt-2 }
458
487
  parent.after(nodes);
459
488
  }
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "default", {
9
9
  const _quickLru = /*#__PURE__*/ _interopRequireDefault(require("quick-lru"));
10
10
  const _sharedState = /*#__PURE__*/ _interopRequireWildcard(require("./sharedState"));
11
11
  const _generateRules = require("./generateRules");
12
- const _bigSign = /*#__PURE__*/ _interopRequireDefault(require("../util/bigSign"));
13
12
  const _log = /*#__PURE__*/ _interopRequireDefault(require("../util/log"));
14
13
  const _cloneNodes = /*#__PURE__*/ _interopRequireDefault(require("../util/cloneNodes"));
15
14
  const _defaultExtractor = require("./defaultExtractor");
@@ -103,49 +102,21 @@ function getClassCandidates(content, extractor, candidates, seen) {
103
102
  }
104
103
  }
105
104
  }
106
- function buildStylesheet(rules, context) {
107
- let sortedRules = rules.sort(([a], [z])=>(0, _bigSign.default)(a - z));
105
+ /**
106
+ *
107
+ * @param {[import('./offsets.js').RuleOffset, import('postcss').Node][]} rules
108
+ * @param {*} context
109
+ */ function buildStylesheet(rules, context) {
110
+ let sortedRules = context.offsets.sort(rules);
108
111
  let returnValue = {
109
112
  base: new Set(),
110
113
  defaults: new Set(),
111
114
  components: new Set(),
112
115
  utilities: new Set(),
113
- variants: new Set(),
114
- // All the CSS that is not Tailwind related can be put in this bucket. This
115
- // will make it easier to later use this information when we want to
116
- // `@apply` for example. The main reason we do this here is because we
117
- // still need to make sure the order is correct. Last but not least, we
118
- // will make sure to always re-inject this section into the css, even if
119
- // certain rules were not used. This means that it will look like a no-op
120
- // from the user's perspective, but we gathered all the useful information
121
- // we need.
122
- user: new Set()
116
+ variants: new Set()
123
117
  };
124
118
  for (let [sort, rule] of sortedRules){
125
- if (sort >= context.minimumScreen) {
126
- returnValue.variants.add(rule);
127
- continue;
128
- }
129
- if (sort & context.layerOrder.base) {
130
- returnValue.base.add(rule);
131
- continue;
132
- }
133
- if (sort & context.layerOrder.defaults) {
134
- returnValue.defaults.add(rule);
135
- continue;
136
- }
137
- if (sort & context.layerOrder.components) {
138
- returnValue.components.add(rule);
139
- continue;
140
- }
141
- if (sort & context.layerOrder.utilities) {
142
- returnValue.utilities.add(rule);
143
- continue;
144
- }
145
- if (sort & context.layerOrder.user) {
146
- returnValue.user.add(rule);
147
- continue;
148
- }
119
+ returnValue[sort.layer].add(rule);
149
120
  }
150
121
  return returnValue;
151
122
  }
@@ -188,14 +159,11 @@ function expandTailwindAtRules(context) {
188
159
  // Generate the actual CSS
189
160
  let classCacheCount = context.classCache.size;
190
161
  env.DEBUG && console.time("Generate rules");
191
- let rules = (0, _generateRules.generateRules)(candidates, context);
162
+ (0, _generateRules.generateRules)(candidates, context);
192
163
  env.DEBUG && console.timeEnd("Generate rules");
193
164
  // We only ever add to the classCache, so if it didn't grow, there is nothing new.
194
165
  env.DEBUG && console.time("Build stylesheet");
195
166
  if (context.stylesheetCache === null || context.classCache.size !== classCacheCount) {
196
- for (let rule of rules){
197
- context.ruleCache.add(rule);
198
- }
199
167
  context.stylesheetCache = buildStylesheet([
200
168
  ...context.ruleCache
201
169
  ], context);
@@ -259,7 +227,7 @@ function expandTailwindAtRules(context) {
259
227
  if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
260
228
  _log.default.warn("content-problems", [
261
229
  "No utility classes were detected in your source files. If this is unexpected, double-check the `content` option in your Tailwind CSS configuration.",
262
- "https://tailwindcss.com/docs/content-configuration",
230
+ "https://tailwindcss.com/docs/content-configuration"
263
231
  ]);
264
232
  }
265
233
  // ---
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "findAtConfigPath", {
6
+ enumerable: true,
7
+ get: ()=>findAtConfigPath
8
+ });
9
+ const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
10
+ const _path = /*#__PURE__*/ _interopRequireDefault(require("path"));
11
+ function _interopRequireDefault(obj) {
12
+ return obj && obj.__esModule ? obj : {
13
+ default: obj
14
+ };
15
+ }
16
+ function findAtConfigPath(root, result) {
17
+ let configPath = null;
18
+ let relativeTo = null;
19
+ root.walkAtRules("config", (rule)=>{
20
+ var ref;
21
+ var _file, ref1;
22
+ relativeTo = (ref1 = (_file = (ref = rule.source) === null || ref === void 0 ? void 0 : ref.input.file) !== null && _file !== void 0 ? _file : result.opts.from) !== null && ref1 !== void 0 ? ref1 : null;
23
+ if (relativeTo === null) {
24
+ throw rule.error("The `@config` directive cannot be used without setting `from` in your PostCSS config.");
25
+ }
26
+ if (configPath) {
27
+ throw rule.error("Only one `@config` directive is allowed per file.");
28
+ }
29
+ let matches = rule.params.match(/(['"])(.*?)\1/);
30
+ if (!matches) {
31
+ throw rule.error("A path is required when using the `@config` directive.");
32
+ }
33
+ let inputPath = matches[2];
34
+ if (_path.default.isAbsolute(inputPath)) {
35
+ throw rule.error("The `@config` directive cannot be used with an absolute path.");
36
+ }
37
+ configPath = _path.default.resolve(_path.default.dirname(relativeTo), inputPath);
38
+ if (!_fs.default.existsSync(configPath)) {
39
+ throw rule.error(`The config file at "${inputPath}" does not exist. Make sure the path is correct and the file exists.`);
40
+ }
41
+ rule.remove();
42
+ });
43
+ return configPath ? configPath : null;
44
+ }