tailwindcss 0.0.0-insiders.4e21639 → 0.0.0-insiders.4e62334

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 (157) hide show
  1. package/CHANGELOG.md +435 -3
  2. package/LICENSE +1 -2
  3. package/README.md +13 -6
  4. package/colors.d.ts +3 -0
  5. package/colors.js +2 -1
  6. package/defaultConfig.d.ts +3 -0
  7. package/defaultConfig.js +2 -1
  8. package/defaultTheme.d.ts +4 -0
  9. package/defaultTheme.js +2 -1
  10. package/lib/cli-peer-dependencies.js +20 -7
  11. package/lib/cli.js +460 -259
  12. package/lib/constants.js +27 -20
  13. package/lib/corePluginList.js +9 -3
  14. package/lib/corePlugins.js +1840 -1753
  15. package/lib/css/preflight.css +8 -9
  16. package/lib/featureFlags.js +29 -20
  17. package/lib/index.js +22 -11
  18. package/lib/lib/cacheInvalidation.js +90 -0
  19. package/lib/lib/collapseAdjacentRules.js +27 -9
  20. package/lib/lib/collapseDuplicateDeclarations.js +58 -4
  21. package/lib/lib/defaultExtractor.js +231 -0
  22. package/lib/lib/detectNesting.js +13 -10
  23. package/lib/lib/evaluateTailwindFunctions.js +119 -52
  24. package/lib/lib/expandApplyAtRules.js +440 -161
  25. package/lib/lib/expandTailwindAtRules.js +130 -128
  26. package/lib/lib/generateRules.js +410 -171
  27. package/lib/lib/getModuleDependencies.js +11 -8
  28. package/lib/lib/normalizeTailwindDirectives.js +43 -32
  29. package/lib/lib/offsets.js +199 -0
  30. package/lib/lib/partitionApplyAtRules.js +56 -0
  31. package/lib/lib/regex.js +60 -0
  32. package/lib/lib/resolveDefaultsAtRules.js +91 -55
  33. package/lib/lib/setupContextUtils.js +453 -347
  34. package/lib/lib/setupTrackingContext.js +52 -44
  35. package/lib/lib/sharedState.js +48 -9
  36. package/lib/lib/substituteScreenAtRules.js +13 -8
  37. package/{nesting → lib/postcss-plugins/nesting}/README.md +2 -2
  38. package/lib/postcss-plugins/nesting/index.js +19 -0
  39. package/lib/postcss-plugins/nesting/plugin.js +87 -0
  40. package/lib/processTailwindFeatures.js +36 -25
  41. package/lib/public/colors.js +247 -245
  42. package/lib/public/create-plugin.js +6 -4
  43. package/lib/public/default-config.js +7 -5
  44. package/lib/public/default-theme.js +7 -5
  45. package/lib/public/resolve-config.js +8 -5
  46. package/lib/util/bigSign.js +4 -1
  47. package/lib/util/buildMediaQuery.js +16 -25
  48. package/lib/util/cloneDeep.js +7 -6
  49. package/lib/util/cloneNodes.js +21 -3
  50. package/lib/util/color.js +54 -40
  51. package/lib/util/configurePlugins.js +4 -1
  52. package/lib/util/createPlugin.js +6 -6
  53. package/lib/util/createUtilityPlugin.js +12 -14
  54. package/lib/util/dataTypes.js +119 -102
  55. package/lib/util/defaults.js +10 -1
  56. package/lib/util/escapeClassName.js +7 -4
  57. package/lib/util/escapeCommas.js +5 -2
  58. package/lib/util/flattenColorPalette.js +9 -12
  59. package/lib/util/formatVariantSelector.js +223 -40
  60. package/lib/util/getAllConfigs.js +27 -8
  61. package/lib/util/hashConfig.js +6 -3
  62. package/lib/util/isKeyframeRule.js +5 -2
  63. package/lib/util/isPlainObject.js +5 -2
  64. package/lib/util/isValidArbitraryValue.js +72 -0
  65. package/lib/util/log.js +22 -12
  66. package/lib/util/nameClass.js +17 -8
  67. package/lib/util/negateValue.js +22 -7
  68. package/lib/util/normalizeConfig.js +99 -54
  69. package/lib/util/normalizeScreens.js +73 -0
  70. package/lib/util/parseAnimationValue.js +42 -40
  71. package/lib/util/parseBoxShadowValue.js +30 -23
  72. package/lib/util/parseDependency.js +18 -15
  73. package/lib/util/parseObjectStyles.js +10 -7
  74. package/lib/util/pluginUtils.js +51 -42
  75. package/lib/util/prefixSelector.js +10 -8
  76. package/lib/util/removeAlphaVariables.js +29 -0
  77. package/lib/util/resolveConfig.js +91 -66
  78. package/lib/util/resolveConfigPath.js +11 -9
  79. package/lib/util/responsive.js +8 -5
  80. package/lib/util/splitAtTopLevelOnly.js +43 -0
  81. package/lib/util/tap.js +4 -1
  82. package/lib/util/toColorValue.js +5 -3
  83. package/lib/util/toPath.js +24 -3
  84. package/lib/util/transformThemeValue.js +37 -29
  85. package/lib/util/validateConfig.js +24 -0
  86. package/lib/util/withAlphaVariable.js +23 -15
  87. package/nesting/index.js +2 -12
  88. package/package.json +43 -43
  89. package/peers/index.js +11543 -8114
  90. package/plugin.d.ts +11 -0
  91. package/plugin.js +2 -1
  92. package/resolveConfig.d.ts +3 -0
  93. package/resolveConfig.js +2 -1
  94. package/scripts/generate-types.js +105 -0
  95. package/scripts/type-utils.js +27 -0
  96. package/src/cli-peer-dependencies.js +7 -1
  97. package/src/cli.js +293 -36
  98. package/src/corePluginList.js +1 -1
  99. package/src/corePlugins.js +428 -285
  100. package/src/css/preflight.css +8 -9
  101. package/src/featureFlags.js +9 -5
  102. package/src/index.js +14 -6
  103. package/src/lib/cacheInvalidation.js +52 -0
  104. package/src/lib/collapseAdjacentRules.js +21 -2
  105. package/src/lib/collapseDuplicateDeclarations.js +66 -1
  106. package/src/lib/defaultExtractor.js +208 -0
  107. package/src/lib/evaluateTailwindFunctions.js +84 -10
  108. package/src/lib/expandApplyAtRules.js +488 -153
  109. package/src/lib/expandTailwindAtRules.js +82 -80
  110. package/src/lib/generateRules.js +352 -120
  111. package/src/lib/normalizeTailwindDirectives.js +7 -1
  112. package/src/lib/offsets.js +239 -0
  113. package/src/lib/partitionApplyAtRules.js +52 -0
  114. package/src/lib/regex.js +74 -0
  115. package/src/lib/resolveDefaultsAtRules.js +59 -17
  116. package/src/lib/setupContextUtils.js +337 -174
  117. package/src/lib/setupTrackingContext.js +13 -8
  118. package/src/lib/sharedState.js +42 -4
  119. package/src/lib/substituteScreenAtRules.js +6 -3
  120. package/src/postcss-plugins/nesting/README.md +42 -0
  121. package/src/postcss-plugins/nesting/index.js +13 -0
  122. package/src/postcss-plugins/nesting/plugin.js +80 -0
  123. package/src/processTailwindFeatures.js +12 -2
  124. package/src/util/buildMediaQuery.js +14 -18
  125. package/src/util/cloneNodes.js +19 -2
  126. package/src/util/color.js +31 -14
  127. package/src/util/dataTypes.js +28 -19
  128. package/src/util/defaults.js +6 -0
  129. package/src/util/formatVariantSelector.js +237 -23
  130. package/src/util/getAllConfigs.js +19 -0
  131. package/src/util/isValidArbitraryValue.js +61 -0
  132. package/src/util/log.js +11 -7
  133. package/src/util/nameClass.js +1 -1
  134. package/src/util/negateValue.js +10 -2
  135. package/src/util/normalizeConfig.js +16 -3
  136. package/src/util/normalizeScreens.js +45 -0
  137. package/src/util/parseBoxShadowValue.js +4 -3
  138. package/src/util/pluginUtils.js +14 -2
  139. package/src/util/prefixSelector.js +7 -5
  140. package/src/util/removeAlphaVariables.js +24 -0
  141. package/src/util/resolveConfig.js +71 -17
  142. package/src/util/splitAtTopLevelOnly.js +45 -0
  143. package/src/util/toPath.js +23 -1
  144. package/src/util/transformThemeValue.js +13 -3
  145. package/src/util/validateConfig.js +13 -0
  146. package/src/util/withAlphaVariable.js +1 -1
  147. package/stubs/defaultConfig.stub.js +24 -3
  148. package/stubs/simpleConfig.stub.js +1 -0
  149. package/types/config.d.ts +334 -0
  150. package/types/generated/.gitkeep +0 -0
  151. package/types/generated/colors.d.ts +276 -0
  152. package/types/generated/corePluginList.d.ts +1 -0
  153. package/types/generated/default-theme.d.ts +331 -0
  154. package/types/index.d.ts +7 -0
  155. package/lib/lib/setupWatchingContext.js +0 -288
  156. package/nesting/plugin.js +0 -41
  157. package/src/lib/setupWatchingContext.js +0 -311
package/lib/cli.js CHANGED
@@ -1,44 +1,84 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
- var _indexJs = require("../peers/index.js");
4
- var _chokidar = _interopRequireDefault(require("chokidar"));
5
- var _path = _interopRequireDefault(require("path"));
6
- var _arg = _interopRequireDefault(require("arg"));
7
- var _fs = _interopRequireDefault(require("fs"));
8
- var _postcssLoadConfig = _interopRequireDefault(require("postcss-load-config"));
9
- var _cosmiconfig = require("cosmiconfig");
10
- var _plugins // Little bit scary, looking at private/internal API
11
- = _interopRequireDefault(require("postcss-load-config/src/plugins"));
12
- var _processTailwindFeatures = _interopRequireDefault(require("./processTailwindFeatures"));
13
- var _resolveConfig = _interopRequireDefault(require("../resolveConfig"));
14
- var _fastGlob = _interopRequireDefault(require("fast-glob"));
15
- var _getModuleDependencies = _interopRequireDefault(require("./lib/getModuleDependencies"));
16
- var _log = _interopRequireDefault(require("./util/log"));
17
- var _packageJson = _interopRequireDefault(require("../package.json"));
18
- var _normalizePath = _interopRequireDefault(require("normalize-path"));
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ const _indexJs = require("../peers/index.js");
7
+ const _chokidar = /*#__PURE__*/ _interopRequireDefault(require("chokidar"));
8
+ const _path = /*#__PURE__*/ _interopRequireDefault(require("path"));
9
+ const _arg = /*#__PURE__*/ _interopRequireDefault(require("arg"));
10
+ const _fs = /*#__PURE__*/ _interopRequireDefault(require("fs"));
11
+ const _postcssLoadConfig = /*#__PURE__*/ _interopRequireDefault(require("postcss-load-config"));
12
+ const _lilconfig = require("lilconfig");
13
+ const _plugins = /*#__PURE__*/ _interopRequireDefault(require("postcss-load-config/src/plugins" // Little bit scary, looking at private/internal API
14
+ ));
15
+ const _options = /*#__PURE__*/ _interopRequireDefault(require("postcss-load-config/src/options" // Little bit scary, looking at private/internal API
16
+ ));
17
+ const _processTailwindFeatures = /*#__PURE__*/ _interopRequireDefault(require("./processTailwindFeatures"));
18
+ const _resolveConfig = /*#__PURE__*/ _interopRequireDefault(require("../resolveConfig"));
19
+ const _fastGlob = /*#__PURE__*/ _interopRequireDefault(require("fast-glob"));
20
+ const _getModuleDependencies = /*#__PURE__*/ _interopRequireDefault(require("./lib/getModuleDependencies"));
21
+ const _log = /*#__PURE__*/ _interopRequireDefault(require("./util/log"));
22
+ const _packageJson = /*#__PURE__*/ _interopRequireDefault(require("../package.json"));
23
+ const _normalizePath = /*#__PURE__*/ _interopRequireDefault(require("normalize-path"));
24
+ const _micromatch = /*#__PURE__*/ _interopRequireDefault(require("micromatch"));
25
+ const _validateConfigJs = require("./util/validateConfig.js");
19
26
  function _interopRequireDefault(obj) {
20
27
  return obj && obj.__esModule ? obj : {
21
28
  default: obj
22
29
  };
23
30
  }
24
31
  let env = {
25
- DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== '0'
32
+ DEBUG: process.env.DEBUG !== undefined && process.env.DEBUG !== "0"
33
+ };
34
+ function isESM() {
35
+ const pkgPath = _path.default.resolve("./package.json");
36
+ try {
37
+ let pkg = JSON.parse(_fs.default.readFileSync(pkgPath, "utf8"));
38
+ return pkg.type && pkg.type === "module";
39
+ } catch (err) {
40
+ return false;
41
+ }
42
+ }
43
+ let configs = isESM() ? {
44
+ tailwind: "tailwind.config.cjs",
45
+ postcss: "postcss.config.cjs"
46
+ } : {
47
+ tailwind: "tailwind.config.js",
48
+ postcss: "postcss.config.js"
26
49
  };
27
50
  // ---
28
51
  function indentRecursive(node, indent = 0) {
29
52
  node.each && node.each((child, i)=>{
30
- if (!child.raws.before || !child.raws.before.trim() || child.raws.before.includes('\n')) {
31
- child.raws.before = `\n${node.type !== 'rule' && i > 0 ? '\n' : ''}${' '.repeat(indent)}`;
53
+ if (!child.raws.before || !child.raws.before.trim() || child.raws.before.includes("\n")) {
54
+ child.raws.before = `\n${node.type !== "rule" && i > 0 ? "\n" : ""}${" ".repeat(indent)}`;
32
55
  }
33
- child.raws.after = `\n${' '.repeat(indent)}`;
56
+ child.raws.after = `\n${" ".repeat(indent)}`;
34
57
  indentRecursive(child, indent + 1);
35
58
  });
36
59
  }
37
60
  function formatNodes(root) {
38
61
  indentRecursive(root);
39
62
  if (root.first) {
40
- root.first.raws.before = '';
63
+ root.first.raws.before = "";
64
+ }
65
+ }
66
+ async function outputFile(file, contents) {
67
+ if (_fs.default.existsSync(file) && await _fs.default.promises.readFile(file, "utf8") === contents) {
68
+ return; // Skip writing the file
41
69
  }
70
+ // Write the file
71
+ await _fs.default.promises.writeFile(file, contents, "utf8");
72
+ }
73
+ function drainStdin() {
74
+ return new Promise((resolve, reject)=>{
75
+ let result = "";
76
+ process.stdin.on("data", (chunk)=>{
77
+ result += chunk;
78
+ });
79
+ process.stdin.on("end", ()=>resolve(result));
80
+ process.stdin.on("error", (err)=>reject(err));
81
+ });
42
82
  }
43
83
  function help({ message , usage , commands , options }) {
44
84
  let indent = 2;
@@ -48,32 +88,31 @@ function help({ message , usage , commands , options }) {
48
88
  // Render message
49
89
  if (message) {
50
90
  console.log();
51
- for (let msg of message.split('\n')){
91
+ for (let msg of message.split("\n")){
52
92
  console.log(msg);
53
93
  }
54
94
  }
55
95
  // Render usage
56
96
  if (usage && usage.length > 0) {
57
97
  console.log();
58
- console.log('Usage:');
98
+ console.log("Usage:");
59
99
  for (let example of usage){
60
- console.log(' '.repeat(indent), example);
100
+ console.log(" ".repeat(indent), example);
61
101
  }
62
102
  }
63
103
  // Render commands
64
104
  if (commands && commands.length > 0) {
65
105
  console.log();
66
- console.log('Commands:');
106
+ console.log("Commands:");
67
107
  for (let command of commands){
68
- console.log(' '.repeat(indent), command);
108
+ console.log(" ".repeat(indent), command);
69
109
  }
70
110
  }
71
111
  // Render options
72
112
  if (options) {
73
- let groupedOptions = {
74
- };
113
+ let groupedOptions = {};
75
114
  for (let [key, value] of Object.entries(options)){
76
- if (typeof value === 'object') {
115
+ if (typeof value === "object") {
77
116
  groupedOptions[key] = {
78
117
  ...value,
79
118
  flags: [
@@ -85,13 +124,13 @@ function help({ message , usage , commands , options }) {
85
124
  }
86
125
  }
87
126
  console.log();
88
- console.log('Options:');
127
+ console.log("Options:");
89
128
  for (let { flags , description , deprecated } of Object.values(groupedOptions)){
90
129
  if (deprecated) continue;
91
130
  if (flags.length === 1) {
92
- console.log(' '.repeat(indent + 4 /* 4 = "-i, ".length */ ), flags.slice().reverse().join(', ').padEnd(20, ' '), description);
131
+ console.log(" ".repeat(indent + 4 /* 4 = "-i, ".length */ ), flags.slice().reverse().join(", ").padEnd(20, " "), description);
93
132
  } else {
94
- console.log(' '.repeat(indent), flags.slice().reverse().join(', ').padEnd(24, ' '), description);
133
+ console.log(" ".repeat(indent), flags.slice().reverse().join(", ").padEnd(24, " "), description);
95
134
  }
96
135
  }
97
136
  }
@@ -105,156 +144,161 @@ function oneOf(...options) {
105
144
  return parsed;
106
145
  }
107
146
  }
108
- throw new Error('...');
147
+ throw new Error("...");
109
148
  }, {
110
149
  manualParsing: true
111
150
  });
112
151
  }
113
- let commands1 = {
152
+ function loadPostcss() {
153
+ // Try to load a local `postcss` version first
154
+ try {
155
+ return require("postcss");
156
+ } catch {}
157
+ return (0, _indexJs.lazyPostcss)();
158
+ }
159
+ let commands = {
114
160
  init: {
115
161
  run: init,
116
162
  args: {
117
- '--full': {
163
+ "--full": {
118
164
  type: Boolean,
119
- description: 'Initialize a full `tailwind.config.js` file'
165
+ description: `Initialize a full \`${configs.tailwind}\` file`
120
166
  },
121
- '--postcss': {
167
+ "--postcss": {
122
168
  type: Boolean,
123
- description: 'Initialize a `postcss.config.js` file'
169
+ description: `Initialize a \`${configs.postcss}\` file`
124
170
  },
125
- '-f': '--full',
126
- '-p': '--postcss'
171
+ "-f": "--full",
172
+ "-p": "--postcss"
127
173
  }
128
174
  },
129
175
  build: {
130
176
  run: build,
131
177
  args: {
132
- '--input': {
178
+ "--input": {
133
179
  type: String,
134
- description: 'Input file'
180
+ description: "Input file"
135
181
  },
136
- '--output': {
182
+ "--output": {
137
183
  type: String,
138
- description: 'Output file'
184
+ description: "Output file"
185
+ },
186
+ "--watch": {
187
+ type: Boolean,
188
+ description: "Watch for changes and rebuild as needed"
139
189
  },
140
- '--watch': {
190
+ "--poll": {
141
191
  type: Boolean,
142
- description: 'Watch for changes and rebuild as needed'
192
+ description: "Use polling instead of filesystem events when watching"
143
193
  },
144
- '--content': {
194
+ "--content": {
145
195
  type: String,
146
- description: 'Content paths to use for removing unused classes'
196
+ description: "Content paths to use for removing unused classes"
147
197
  },
148
- '--purge': {
198
+ "--purge": {
149
199
  type: String,
150
200
  deprecated: true
151
201
  },
152
- '--postcss': {
202
+ "--postcss": {
153
203
  type: oneOf(String, Boolean),
154
- description: 'Load custom PostCSS configuration'
204
+ description: "Load custom PostCSS configuration"
155
205
  },
156
- '--minify': {
206
+ "--minify": {
157
207
  type: Boolean,
158
- description: 'Minify the output'
208
+ description: "Minify the output"
159
209
  },
160
- '--config': {
210
+ "--config": {
161
211
  type: String,
162
- description: 'Path to a custom config file'
212
+ description: "Path to a custom config file"
163
213
  },
164
- '--no-autoprefixer': {
214
+ "--no-autoprefixer": {
165
215
  type: Boolean,
166
- description: 'Disable autoprefixer'
216
+ description: "Disable autoprefixer"
167
217
  },
168
- '-c': '--config',
169
- '-i': '--input',
170
- '-o': '--output',
171
- '-m': '--minify',
172
- '-w': '--watch'
218
+ "-c": "--config",
219
+ "-i": "--input",
220
+ "-o": "--output",
221
+ "-m": "--minify",
222
+ "-w": "--watch",
223
+ "-p": "--poll"
173
224
  }
174
225
  }
175
226
  };
176
227
  let sharedFlags = {
177
- '--help': {
228
+ "--help": {
178
229
  type: Boolean,
179
- description: 'Display usage information'
230
+ description: "Display usage information"
180
231
  },
181
- '-h': '--help'
232
+ "-h": "--help"
182
233
  };
183
- if (process.stdout.isTTY /* Detect redirecting output to a file */ && (process.argv[2] === undefined || process.argv.slice(2).every((flag)=>sharedFlags[flag] !== undefined
184
- ))) {
234
+ if (process.stdout.isTTY /* Detect redirecting output to a file */ && (process.argv[2] === undefined || process.argv.slice(2).every((flag)=>sharedFlags[flag] !== undefined))) {
185
235
  help({
186
236
  usage: [
187
- 'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]',
188
- 'tailwindcss init [--full] [--postcss] [options...]',
237
+ "tailwindcss [--input input.css] [--output output.css] [--watch] [options...]",
238
+ "tailwindcss init [--full] [--postcss] [options...]",
189
239
  ],
190
- commands: Object.keys(commands1).filter((command)=>command !== 'build'
191
- ).map((command)=>`${command} [options]`
192
- ),
240
+ commands: Object.keys(commands).filter((command)=>command !== "build").map((command)=>`${command} [options]`),
193
241
  options: {
194
- ...commands1.build.args,
242
+ ...commands.build.args,
195
243
  ...sharedFlags
196
244
  }
197
245
  });
198
246
  process.exit(0);
199
247
  }
200
- let command1 = ((arg = '')=>arg.startsWith('-') ? undefined : arg
201
- )(process.argv[2]) || 'build';
202
- if (commands1[command1] === undefined) {
203
- if (_fs.default.existsSync(_path.default.resolve(command1))) {
248
+ let command = ((arg = "")=>arg.startsWith("-") ? undefined : arg)(process.argv[2]) || "build";
249
+ if (commands[command] === undefined) {
250
+ if (_fs.default.existsSync(_path.default.resolve(command))) {
204
251
  // TODO: Deprecate this in future versions
205
252
  // Check if non-existing command, might be a file.
206
- command1 = 'build';
253
+ command = "build";
207
254
  } else {
208
255
  help({
209
- message: `Invalid command: ${command1}`,
256
+ message: `Invalid command: ${command}`,
210
257
  usage: [
211
- 'tailwindcss <command> [options]'
258
+ "tailwindcss <command> [options]"
212
259
  ],
213
- commands: Object.keys(commands1).filter((command)=>command !== 'build'
214
- ).map((command)=>`${command} [options]`
215
- ),
260
+ commands: Object.keys(commands).filter((command)=>command !== "build").map((command)=>`${command} [options]`),
216
261
  options: sharedFlags
217
262
  });
218
263
  process.exit(1);
219
264
  }
220
265
  }
221
266
  // Execute command
222
- let { args: flags1 , run } = commands1[command1];
223
- let args1 = (()=>{
267
+ let { args: flags , run } = commands[command];
268
+ let args = (()=>{
224
269
  try {
225
- let result = (0, _arg).default(Object.fromEntries(Object.entries({
226
- ...flags1,
270
+ let result = (0, _arg.default)(Object.fromEntries(Object.entries({
271
+ ...flags,
227
272
  ...sharedFlags
228
273
  }).filter(([_key, value])=>{
229
274
  var ref;
230
275
  return !(value === null || value === void 0 ? void 0 : (ref = value.type) === null || ref === void 0 ? void 0 : ref.manualParsing);
231
276
  }).map(([key, value])=>[
232
277
  key,
233
- typeof value === 'object' ? value.type : value
234
- ]
235
- )), {
278
+ typeof value === "object" ? value.type : value
279
+ ])), {
236
280
  permissive: true
237
281
  });
238
282
  // Manual parsing of flags to allow for special flags like oneOf(Boolean, String)
239
- for(let i = result['_'].length - 1; i >= 0; --i){
240
- let flag = result['_'][i];
241
- if (!flag.startsWith('-')) continue;
283
+ for(let i = result["_"].length - 1; i >= 0; --i){
284
+ let flag = result["_"][i];
285
+ if (!flag.startsWith("-")) continue;
242
286
  let flagName = flag;
243
- let handler = flags1[flag];
287
+ let handler = flags[flag];
244
288
  // Resolve flagName & handler
245
- while(typeof handler === 'string'){
289
+ while(typeof handler === "string"){
246
290
  flagName = handler;
247
- handler = flags1[handler];
291
+ handler = flags[handler];
248
292
  }
249
293
  if (!handler) continue;
250
294
  let args = [];
251
295
  let offset = i + 1;
252
296
  // Parse args for current flag
253
- while(result['_'][offset] && !result['_'][offset].startsWith('-')){
254
- args.push(result['_'][offset++]);
297
+ while(result["_"][offset] && !result["_"][offset].startsWith("-")){
298
+ args.push(result["_"][offset++]);
255
299
  }
256
300
  // Cleanup manually parsed flags + args
257
- result['_'].splice(i, 1 + args.length);
301
+ result["_"].splice(i, 1 + args.length);
258
302
  // Set the resolved value in the `result` object
259
303
  result[flagName] = handler.type(args.length === 0 ? undefined : args.length === 1 ? args[0] : args, flagName);
260
304
  }
@@ -264,16 +308,16 @@ let args1 = (()=>{
264
308
  //
265
309
  // E.g.: tailwindcss input.css -> _: ['build', 'input.css']
266
310
  // E.g.: tailwindcss build input.css -> _: ['build', 'input.css']
267
- if (result['_'][0] !== command1) {
268
- result['_'].unshift(command1);
311
+ if (result["_"][0] !== command) {
312
+ result["_"].unshift(command);
269
313
  }
270
314
  return result;
271
315
  } catch (err) {
272
- if (err.code === 'ARG_UNKNOWN_OPTION') {
316
+ if (err.code === "ARG_UNKNOWN_OPTION") {
273
317
  help({
274
318
  message: err.message,
275
319
  usage: [
276
- 'tailwindcss <command> [options]'
320
+ "tailwindcss <command> [options]"
277
321
  ],
278
322
  options: sharedFlags
279
323
  });
@@ -282,14 +326,14 @@ let args1 = (()=>{
282
326
  throw err;
283
327
  }
284
328
  })();
285
- if (args1['--help']) {
329
+ if (args["--help"]) {
286
330
  help({
287
331
  options: {
288
- ...flags1,
332
+ ...flags,
289
333
  ...sharedFlags
290
334
  },
291
335
  usage: [
292
- `tailwindcss ${command1} [options]`
336
+ `tailwindcss ${command} [options]`
293
337
  ]
294
338
  });
295
339
  process.exit(0);
@@ -299,23 +343,23 @@ run();
299
343
  function init() {
300
344
  let messages = [];
301
345
  var ref;
302
- let tailwindConfigLocation = _path.default.resolve((ref = args1['_'][1]) !== null && ref !== void 0 ? ref : './tailwind.config.js');
346
+ let tailwindConfigLocation = _path.default.resolve((ref = args["_"][1]) !== null && ref !== void 0 ? ref : `./${configs.tailwind}`);
303
347
  if (_fs.default.existsSync(tailwindConfigLocation)) {
304
348
  messages.push(`${_path.default.basename(tailwindConfigLocation)} already exists.`);
305
349
  } else {
306
- let stubFile = _fs.default.readFileSync(args1['--full'] ? _path.default.resolve(__dirname, '../stubs/defaultConfig.stub.js') : _path.default.resolve(__dirname, '../stubs/simpleConfig.stub.js'), 'utf8');
350
+ let stubFile = _fs.default.readFileSync(args["--full"] ? _path.default.resolve(__dirname, "../stubs/defaultConfig.stub.js") : _path.default.resolve(__dirname, "../stubs/simpleConfig.stub.js"), "utf8");
307
351
  // Change colors import
308
- stubFile = stubFile.replace('../colors', 'tailwindcss/colors');
309
- _fs.default.writeFileSync(tailwindConfigLocation, stubFile, 'utf8');
352
+ stubFile = stubFile.replace("../colors", "tailwindcss/colors");
353
+ _fs.default.writeFileSync(tailwindConfigLocation, stubFile, "utf8");
310
354
  messages.push(`Created Tailwind CSS config file: ${_path.default.basename(tailwindConfigLocation)}`);
311
355
  }
312
- if (args1['--postcss']) {
313
- let postcssConfigLocation = _path.default.resolve('./postcss.config.js');
356
+ if (args["--postcss"]) {
357
+ let postcssConfigLocation = _path.default.resolve(`./${configs.postcss}`);
314
358
  if (_fs.default.existsSync(postcssConfigLocation)) {
315
359
  messages.push(`${_path.default.basename(postcssConfigLocation)} already exists.`);
316
360
  } else {
317
- let stubFile = _fs.default.readFileSync(_path.default.resolve(__dirname, '../stubs/defaultPostCssConfig.stub.js'), 'utf8');
318
- _fs.default.writeFileSync(postcssConfigLocation, stubFile, 'utf8');
361
+ let stubFile1 = _fs.default.readFileSync(_path.default.resolve(__dirname, "../stubs/defaultPostCssConfig.stub.js"), "utf8");
362
+ _fs.default.writeFileSync(postcssConfigLocation, stubFile1, "utf8");
319
363
  messages.push(`Created PostCSS config file: ${_path.default.basename(postcssConfigLocation)}`);
320
364
  }
321
365
  }
@@ -327,50 +371,55 @@ function init() {
327
371
  }
328
372
  }
329
373
  async function build() {
330
- let input = args1['--input'];
331
- let output = args1['--output'];
332
- let shouldWatch = args1['--watch'];
333
- let includePostCss = args1['--postcss'];
374
+ let input = args["--input"];
375
+ let output = args["--output"];
376
+ let shouldWatch = args["--watch"];
377
+ let shouldPoll = args["--poll"];
378
+ let shouldCoalesceWriteEvents = shouldPoll || process.platform === "win32";
379
+ let includePostCss = args["--postcss"];
380
+ // Polling interval in milliseconds
381
+ // Used only when polling or coalescing add/change events on Windows
382
+ let pollInterval = 10;
334
383
  // TODO: Deprecate this in future versions
335
- if (!input && args1['_'][1]) {
336
- console.error('[deprecation] Running tailwindcss without -i, please provide an input file.');
337
- input = args1['--input'] = args1['_'][1];
384
+ if (!input && args["_"][1]) {
385
+ console.error("[deprecation] Running tailwindcss without -i, please provide an input file.");
386
+ input = args["--input"] = args["_"][1];
338
387
  }
339
- if (input && !_fs.default.existsSync(input = _path.default.resolve(input))) {
340
- console.error(`Specified input file ${args1['--input']} does not exist.`);
388
+ if (input && input !== "-" && !_fs.default.existsSync(input = _path.default.resolve(input))) {
389
+ console.error(`Specified input file ${args["--input"]} does not exist.`);
341
390
  process.exit(9);
342
391
  }
343
- if (args1['--config'] && !_fs.default.existsSync(args1['--config'] = _path.default.resolve(args1['--config']))) {
344
- console.error(`Specified config file ${args1['--config']} does not exist.`);
392
+ if (args["--config"] && !_fs.default.existsSync(args["--config"] = _path.default.resolve(args["--config"]))) {
393
+ console.error(`Specified config file ${args["--config"]} does not exist.`);
345
394
  process.exit(9);
346
395
  }
347
- let configPath = args1['--config'] ? args1['--config'] : ((defaultPath)=>_fs.default.existsSync(defaultPath) ? defaultPath : null
348
- )(_path.default.resolve('./tailwind.config.js'));
396
+ let configPath = args["--config"] ? args["--config"] : ((defaultPath)=>_fs.default.existsSync(defaultPath) ? defaultPath : null)(_path.default.resolve(`./${configs.tailwind}`));
349
397
  async function loadPostCssPlugins() {
350
- let customPostCssPath = typeof args1['--postcss'] === 'string' ? args1['--postcss'] : undefined;
351
- let { plugins: configPlugins } = customPostCssPath ? await (async ()=>{
398
+ let customPostCssPath = typeof args["--postcss"] === "string" ? args["--postcss"] : undefined;
399
+ let config = customPostCssPath ? await (async ()=>{
352
400
  let file = _path.default.resolve(customPostCssPath);
353
- // Implementation, see: https://unpkg.com/browse/postcss-load-config@3.0.1/src/index.js
354
- let { config ={
355
- } } = await (0, _cosmiconfig).cosmiconfig('postcss').load(file);
356
- if (typeof config === 'function') {
401
+ // Implementation, see: https://unpkg.com/browse/postcss-load-config@3.1.0/src/index.js
402
+ let { config ={} } = await (0, _lilconfig.lilconfig)("postcss").load(file);
403
+ if (typeof config === "function") {
357
404
  config = config();
358
405
  } else {
359
- config = Object.assign({
360
- }, config);
406
+ config = Object.assign({}, config);
361
407
  }
362
408
  if (!config.plugins) {
363
409
  config.plugins = [];
364
410
  }
365
411
  return {
366
- plugins: (0, _plugins).default(config, file)
412
+ file,
413
+ plugins: (0, _plugins.default)(config, file),
414
+ options: (0, _options.default)(config, file)
367
415
  };
368
- })() : await (0, _postcssLoadConfig).default();
416
+ })() : await (0, _postcssLoadConfig.default)();
417
+ let configPlugins = config.plugins;
369
418
  let configPluginTailwindIdx = configPlugins.findIndex((plugin)=>{
370
- if (typeof plugin === 'function' && plugin.name === 'tailwindcss') {
419
+ if (typeof plugin === "function" && plugin.name === "tailwindcss") {
371
420
  return true;
372
421
  }
373
- if (typeof plugin === 'object' && plugin !== null && plugin.postcssPlugin === 'tailwindcss') {
422
+ if (typeof plugin === "object" && plugin !== null && plugin.postcssPlugin === "tailwindcss") {
374
423
  return true;
375
424
  }
376
425
  return false;
@@ -379,39 +428,84 @@ async function build() {
379
428
  let afterPlugins = configPluginTailwindIdx === -1 ? configPlugins : configPlugins.slice(configPluginTailwindIdx + 1);
380
429
  return [
381
430
  beforePlugins,
382
- afterPlugins
431
+ afterPlugins,
432
+ config.options
433
+ ];
434
+ }
435
+ function loadBuiltinPostcssPlugins() {
436
+ let postcss = loadPostcss();
437
+ let IMPORT_COMMENT = "__TAILWIND_RESTORE_IMPORT__: ";
438
+ return [
439
+ [
440
+ (root)=>{
441
+ root.walkAtRules("import", (rule)=>{
442
+ if (rule.params.slice(1).startsWith("tailwindcss/")) {
443
+ rule.after(postcss.comment({
444
+ text: IMPORT_COMMENT + rule.params
445
+ }));
446
+ rule.remove();
447
+ }
448
+ });
449
+ },
450
+ (()=>{
451
+ try {
452
+ return require("postcss-import");
453
+ } catch {}
454
+ return (0, _indexJs.lazyPostcssImport)();
455
+ })(),
456
+ (root)=>{
457
+ root.walkComments((rule)=>{
458
+ if (rule.text.startsWith(IMPORT_COMMENT)) {
459
+ rule.after(postcss.atRule({
460
+ name: "import",
461
+ params: rule.text.replace(IMPORT_COMMENT, "")
462
+ }));
463
+ rule.remove();
464
+ }
465
+ });
466
+ },
467
+ ],
468
+ [],
469
+ {},
383
470
  ];
384
471
  }
385
472
  function resolveConfig() {
386
- let config = configPath ? require(configPath) : {
387
- };
388
- let resolvedConfig = (0, _resolveConfig).default(config);
389
- if (args1['--purge']) {
390
- _log.default.warn('purge-flag-deprecated', [
391
- 'The `--purge` flag has been deprecated.',
392
- 'Please use `--content` instead.',
473
+ let config = configPath ? require(configPath) : {};
474
+ if (args["--purge"]) {
475
+ _log.default.warn("purge-flag-deprecated", [
476
+ "The `--purge` flag has been deprecated.",
477
+ "Please use `--content` instead.",
393
478
  ]);
394
- if (!args1['--content']) {
395
- args1['--content'] = args1['--purge'];
479
+ if (!args["--content"]) {
480
+ args["--content"] = args["--purge"];
396
481
  }
397
482
  }
398
- if (args1['--content']) {
399
- resolvedConfig.content.files = args1['--content'].split(/(?<!{[^}]+),/);
483
+ if (args["--content"]) {
484
+ let files = args["--content"].split(/(?<!{[^}]+),/);
485
+ let resolvedConfig = (0, _resolveConfig.default)(config, {
486
+ content: {
487
+ files
488
+ }
489
+ });
490
+ resolvedConfig.content.files = files;
491
+ resolvedConfig = (0, _validateConfigJs.validateConfig)(resolvedConfig);
492
+ return resolvedConfig;
400
493
  }
401
- return resolvedConfig;
494
+ let resolvedConfig1 = (0, _resolveConfig.default)(config);
495
+ resolvedConfig1 = (0, _validateConfigJs.validateConfig)(resolvedConfig1);
496
+ return resolvedConfig1;
402
497
  }
403
498
  function extractFileGlobs(config) {
404
499
  return config.content.files.filter((file)=>{
405
500
  // Strings in this case are files / globs. If it is something else,
406
501
  // like an object it's probably a raw content object. But this object
407
502
  // is not watchable, so let's remove it.
408
- return typeof file === 'string';
409
- }).map((glob)=>(0, _normalizePath).default(glob)
410
- );
503
+ return typeof file === "string";
504
+ }).map((glob)=>(0, _normalizePath.default)(glob));
411
505
  }
412
506
  function extractRawContent(config) {
413
507
  return config.content.files.filter((file)=>{
414
- return typeof file === 'object' && file !== null;
508
+ return typeof file === "object" && file !== null;
415
509
  });
416
510
  }
417
511
  function getChangedContent(config) {
@@ -421,12 +515,12 @@ async function build() {
421
515
  let files = _fastGlob.default.sync(globs);
422
516
  for (let file of files){
423
517
  changedContent.push({
424
- content: _fs.default.readFileSync(_path.default.resolve(file), 'utf8'),
518
+ content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
425
519
  extension: _path.default.extname(file).slice(1)
426
520
  });
427
521
  }
428
522
  // Resolve raw content in the tailwind config
429
- for (let { raw: content , extension ='html' } of extractRawContent(config)){
523
+ for (let { raw: content , extension ="html" } of extractRawContent(config)){
430
524
  changedContent.push({
431
525
  content,
432
526
  extension
@@ -439,9 +533,9 @@ async function build() {
439
533
  let changedContent = getChangedContent(config);
440
534
  let tailwindPlugin = ()=>{
441
535
  return {
442
- postcssPlugin: 'tailwindcss',
536
+ postcssPlugin: "tailwindcss",
443
537
  Once (root, { result }) {
444
- (0, _processTailwindFeatures).default(({ createContext })=>{
538
+ (0, _processTailwindFeatures.default)(({ createContext })=>{
445
539
  return ()=>{
446
540
  return createContext(config, changedContent);
447
541
  };
@@ -450,27 +544,23 @@ async function build() {
450
544
  };
451
545
  };
452
546
  tailwindPlugin.postcss = true;
453
- let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [
454
- [],
455
- []
456
- ];
547
+ let [beforePlugins, afterPlugins, postcssOptions] = includePostCss ? await loadPostCssPlugins() : loadBuiltinPostcssPlugins();
457
548
  let plugins = [
458
549
  ...beforePlugins,
459
550
  tailwindPlugin,
460
- !args1['--minify'] && formatNodes,
551
+ !args["--minify"] && formatNodes,
461
552
  ...afterPlugins,
462
- !args1['--no-autoprefixer'] && (()=>{
553
+ !args["--no-autoprefixer"] && (()=>{
463
554
  // Try to load a local `autoprefixer` version first
464
555
  try {
465
- return require('autoprefixer');
466
- } catch {
467
- }
468
- return (0, _indexJs).lazyAutoprefixer();
556
+ return require("autoprefixer");
557
+ } catch {}
558
+ return (0, _indexJs.lazyAutoprefixer)();
469
559
  })(),
470
- args1['--minify'] && (()=>{
560
+ args["--minify"] && (()=>{
471
561
  let options = {
472
562
  preset: [
473
- 'default',
563
+ "default",
474
564
  {
475
565
  cssDeclarationSorter: false
476
566
  }
@@ -478,40 +568,48 @@ async function build() {
478
568
  };
479
569
  // Try to load a local `cssnano` version first
480
570
  try {
481
- return require('cssnano');
482
- } catch {
483
- }
484
- return (0, _indexJs).lazyCssnano()(options);
571
+ return require("cssnano");
572
+ } catch {}
573
+ return (0, _indexJs.lazyCssnano)()(options);
485
574
  })(),
486
575
  ].filter(Boolean);
487
- let processor = (0, _indexJs).postcss(plugins);
576
+ let postcss = loadPostcss();
577
+ let processor = postcss(plugins);
488
578
  function processCSS(css) {
489
579
  let start = process.hrtime.bigint();
490
580
  return Promise.resolve().then(()=>output ? _fs.default.promises.mkdir(_path.default.dirname(output), {
491
581
  recursive: true
492
- }) : null
493
- ).then(()=>processor.process(css, {
582
+ }) : null).then(()=>processor.process(css, {
583
+ ...postcssOptions,
494
584
  from: input,
495
585
  to: output
496
- })
497
- ).then((result)=>{
586
+ })).then((result)=>{
498
587
  if (!output) {
499
588
  return process.stdout.write(result.css);
500
589
  }
501
590
  return Promise.all([
502
- _fs.default.promises.writeFile(output, result.css, ()=>true
503
- ),
504
- result.map && _fs.default.writeFile(output + '.map', result.map.toString(), ()=>true
505
- ),
591
+ outputFile(output, result.css),
592
+ result.map && outputFile(output + ".map", result.map.toString()),
506
593
  ].filter(Boolean));
507
594
  }).then(()=>{
508
595
  let end = process.hrtime.bigint();
509
596
  console.error();
510
- console.error('Done in', (end - start) / BigInt(1000000) + 'ms.');
597
+ console.error("Done in", (end - start) / BigInt(1e6) + "ms.");
511
598
  });
512
599
  }
513
- let css1 = input ? _fs.default.readFileSync(_path.default.resolve(input), 'utf8') : '@tailwind base; @tailwind components; @tailwind utilities';
514
- return processCSS(css1);
600
+ let css = await (()=>{
601
+ // Piping in data, let's drain the stdin
602
+ if (input === "-") {
603
+ return drainStdin();
604
+ }
605
+ // Input file has been provided
606
+ if (input) {
607
+ return _fs.default.readFileSync(_path.default.resolve(input), "utf8");
608
+ }
609
+ // No input file provided, fallback to default atrules
610
+ return "@tailwind base; @tailwind components; @tailwind utilities";
611
+ })();
612
+ return processCSS(css);
515
613
  }
516
614
  let context = null;
517
615
  async function startWatcher() {
@@ -520,41 +618,36 @@ async function build() {
520
618
  let contextDependencies = new Set();
521
619
  let watcher = null;
522
620
  function refreshConfig() {
523
- env.DEBUG && console.time('Module dependencies');
524
- for (let file1 of configDependencies){
525
- delete require.cache[require.resolve(file1)];
621
+ env.DEBUG && console.time("Module dependencies");
622
+ for (let file of configDependencies){
623
+ delete require.cache[require.resolve(file)];
526
624
  }
527
625
  if (configPath) {
528
- configDependencies = (0, _getModuleDependencies).default(configPath).map(({ file })=>file
529
- );
626
+ configDependencies = (0, _getModuleDependencies.default)(configPath).map(({ file })=>file);
530
627
  for (let dependency of configDependencies){
531
628
  contextDependencies.add(dependency);
532
629
  }
533
630
  }
534
- env.DEBUG && console.timeEnd('Module dependencies');
631
+ env.DEBUG && console.timeEnd("Module dependencies");
535
632
  return resolveConfig();
536
633
  }
537
- let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : [
538
- [],
539
- []
540
- ];
634
+ let [beforePlugins, afterPlugins] = includePostCss ? await loadPostCssPlugins() : loadBuiltinPostcssPlugins();
541
635
  let plugins = [
542
636
  ...beforePlugins,
543
- '__TAILWIND_PLUGIN_POSITION__',
544
- !args1['--minify'] && formatNodes,
637
+ "__TAILWIND_PLUGIN_POSITION__",
638
+ !args["--minify"] && formatNodes,
545
639
  ...afterPlugins,
546
- !args1['--no-autoprefixer'] && (()=>{
640
+ !args["--no-autoprefixer"] && (()=>{
547
641
  // Try to load a local `autoprefixer` version first
548
642
  try {
549
- return require('autoprefixer');
550
- } catch {
551
- }
552
- return (0, _indexJs).lazyAutoprefixer();
643
+ return require("autoprefixer");
644
+ } catch {}
645
+ return (0, _indexJs.lazyAutoprefixer)();
553
646
  })(),
554
- args1['--minify'] && (()=>{
647
+ args["--minify"] && (()=>{
555
648
  let options = {
556
649
  preset: [
557
- 'default',
650
+ "default",
558
651
  {
559
652
  cssDeclarationSorter: false
560
653
  }
@@ -562,54 +655,52 @@ async function build() {
562
655
  };
563
656
  // Try to load a local `cssnano` version first
564
657
  try {
565
- return require('cssnano');
566
- } catch {
567
- }
568
- return (0, _indexJs).lazyCssnano()(options);
658
+ return require("cssnano");
659
+ } catch {}
660
+ return (0, _indexJs.lazyCssnano)()(options);
569
661
  })(),
570
662
  ].filter(Boolean);
571
663
  async function rebuild(config) {
572
- env.DEBUG && console.time('Finished in');
664
+ env.DEBUG && console.time("Finished in");
573
665
  let tailwindPlugin = ()=>{
574
666
  return {
575
- postcssPlugin: 'tailwindcss',
667
+ postcssPlugin: "tailwindcss",
576
668
  Once (root, { result }) {
577
- env.DEBUG && console.time('Compiling CSS');
578
- (0, _processTailwindFeatures).default(({ createContext })=>{
669
+ env.DEBUG && console.time("Compiling CSS");
670
+ (0, _processTailwindFeatures.default)(({ createContext })=>{
579
671
  console.error();
580
- console.error('Rebuilding...');
672
+ console.error("Rebuilding...");
581
673
  return ()=>{
582
674
  if (context !== null) {
583
675
  context.changedContent = changedContent.splice(0);
584
676
  return context;
585
677
  }
586
- env.DEBUG && console.time('Creating context');
678
+ env.DEBUG && console.time("Creating context");
587
679
  context = createContext(config, changedContent.splice(0));
588
- env.DEBUG && console.timeEnd('Creating context');
680
+ env.DEBUG && console.timeEnd("Creating context");
589
681
  return context;
590
682
  };
591
683
  })(root, result);
592
- env.DEBUG && console.timeEnd('Compiling CSS');
684
+ env.DEBUG && console.timeEnd("Compiling CSS");
593
685
  }
594
686
  };
595
687
  };
596
688
  tailwindPlugin.postcss = true;
597
- let tailwindPluginIdx = plugins.indexOf('__TAILWIND_PLUGIN_POSITION__');
689
+ let tailwindPluginIdx = plugins.indexOf("__TAILWIND_PLUGIN_POSITION__");
598
690
  let copy = plugins.slice();
599
691
  copy.splice(tailwindPluginIdx, 1, tailwindPlugin);
600
- let processor = (0, _indexJs).postcss(copy);
692
+ let postcss = loadPostcss();
693
+ let processor = postcss(copy);
601
694
  function processCSS(css) {
602
695
  let start = process.hrtime.bigint();
603
696
  return Promise.resolve().then(()=>output ? _fs.default.promises.mkdir(_path.default.dirname(output), {
604
697
  recursive: true
605
- }) : null
606
- ).then(()=>processor.process(css, {
698
+ }) : null).then(()=>processor.process(css, {
607
699
  from: input,
608
700
  to: output
609
- })
610
- ).then(async (result)=>{
701
+ })).then(async (result)=>{
611
702
  for (let message of result.messages){
612
- if (message.type === 'dependency') {
703
+ if (message.type === "dependency") {
613
704
  contextDependencies.add(message.file);
614
705
  }
615
706
  }
@@ -619,85 +710,195 @@ async function build() {
619
710
  if (!output) {
620
711
  return process.stdout.write(result.css);
621
712
  }
622
- await Promise.all([
623
- _fs.default.promises.writeFile(output, result.css, ()=>true
624
- ),
625
- result.map && _fs.default.writeFile(output + '.map', result.map.toString(), ()=>true
626
- ),
713
+ return Promise.all([
714
+ outputFile(output, result.css),
715
+ result.map && outputFile(output + ".map", result.map.toString()),
627
716
  ].filter(Boolean));
628
717
  }).then(()=>{
629
718
  let end = process.hrtime.bigint();
630
- console.error('Done in', (end - start) / BigInt(1000000) + 'ms.');
719
+ console.error("Done in", (end - start) / BigInt(1e6) + "ms.");
631
720
  }).catch((err)=>{
632
- if (err.name === 'CssSyntaxError') {
721
+ if (err.name === "CssSyntaxError") {
633
722
  console.error(err.toString());
634
723
  } else {
635
724
  console.error(err);
636
725
  }
637
726
  });
638
727
  }
639
- let css2 = input ? _fs.default.readFileSync(_path.default.resolve(input), 'utf8') : '@tailwind base; @tailwind components; @tailwind utilities';
640
- let result1 = await processCSS(css2);
641
- env.DEBUG && console.timeEnd('Finished in');
642
- return result1;
728
+ let css = await (()=>{
729
+ // Piping in data, let's drain the stdin
730
+ if (input === "-") {
731
+ return drainStdin();
732
+ }
733
+ // Input file has been provided
734
+ if (input) {
735
+ return _fs.default.readFileSync(_path.default.resolve(input), "utf8");
736
+ }
737
+ // No input file provided, fallback to default atrules
738
+ return "@tailwind base; @tailwind components; @tailwind utilities";
739
+ })();
740
+ let result = await processCSS(css);
741
+ env.DEBUG && console.timeEnd("Finished in");
742
+ return result;
743
+ }
744
+ let config = refreshConfig(configPath);
745
+ let contentPatterns = refreshContentPatterns(config);
746
+ /**
747
+ * @param {import('../types/config.js').RequiredConfig} config
748
+ * @return {{all: string[], dynamic: string[], static: string[]}}
749
+ **/ function refreshContentPatterns(config) {
750
+ let globs = extractFileGlobs(config);
751
+ let tasks = _fastGlob.default.generateTasks(globs, {
752
+ absolute: true
753
+ });
754
+ let dynamicPatterns = tasks.filter((task)=>task.dynamic).flatMap((task)=>task.patterns);
755
+ let staticPatterns = tasks.filter((task)=>!task.dynamic).flatMap((task)=>task.patterns);
756
+ return {
757
+ all: [
758
+ ...staticPatterns,
759
+ ...dynamicPatterns
760
+ ],
761
+ dynamic: dynamicPatterns
762
+ };
643
763
  }
644
- let config1 = refreshConfig(configPath);
645
764
  if (input) {
646
765
  contextDependencies.add(_path.default.resolve(input));
647
766
  }
648
767
  watcher = _chokidar.default.watch([
649
768
  ...contextDependencies,
650
- ...extractFileGlobs(config1)
769
+ ...extractFileGlobs(config)
651
770
  ], {
771
+ // Force checking for atomic writes in all situations
772
+ // This causes chokidar to wait up to 100ms for a file to re-added after it's been unlinked
773
+ // This only works when watching directories though
774
+ atomic: true,
775
+ usePolling: shouldPoll,
776
+ interval: shouldPoll ? pollInterval : undefined,
652
777
  ignoreInitial: true,
653
- awaitWriteFinish: process.platform === 'win32' ? {
778
+ awaitWriteFinish: shouldCoalesceWriteEvents ? {
654
779
  stabilityThreshold: 50,
655
- pollInterval: 10
780
+ pollInterval: pollInterval
656
781
  } : false
657
782
  });
658
783
  let chain = Promise.resolve();
659
- watcher.on('change', async (file)=>{
784
+ let pendingRebuilds = new Set();
785
+ watcher.on("change", async (file)=>{
660
786
  if (contextDependencies.has(file)) {
661
- env.DEBUG && console.time('Resolve config');
787
+ env.DEBUG && console.time("Resolve config");
662
788
  context = null;
663
- config1 = refreshConfig(configPath);
664
- env.DEBUG && console.timeEnd('Resolve config');
665
- env.DEBUG && console.time('Watch new files');
666
- let globs = extractFileGlobs(config1);
789
+ config = refreshConfig(configPath);
790
+ contentPatterns = refreshContentPatterns(config);
791
+ env.DEBUG && console.timeEnd("Resolve config");
792
+ env.DEBUG && console.time("Watch new files");
793
+ let globs = extractFileGlobs(config);
667
794
  watcher.add(configDependencies);
668
795
  watcher.add(globs);
669
- env.DEBUG && console.timeEnd('Watch new files');
796
+ env.DEBUG && console.timeEnd("Watch new files");
670
797
  chain = chain.then(async ()=>{
671
- changedContent.push(...getChangedContent(config1));
672
- await rebuild(config1);
798
+ changedContent.push(...getChangedContent(config));
799
+ await rebuild(config);
673
800
  });
674
801
  } else {
675
802
  chain = chain.then(async ()=>{
676
803
  changedContent.push({
677
- content: _fs.default.readFileSync(_path.default.resolve(file), 'utf8'),
804
+ content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
678
805
  extension: _path.default.extname(file).slice(1)
679
806
  });
680
- await rebuild(config1);
807
+ await rebuild(config);
681
808
  });
682
809
  }
683
810
  });
684
- watcher.on('add', async (file)=>{
811
+ /**
812
+ * When rapidly saving files atomically a couple of situations can happen:
813
+ * - The file is missing since the external program has deleted it by the time we've gotten around to reading it from the earlier save.
814
+ * - The file is being written to by the external program by the time we're going to read it and is thus treated as busy because a lock is held.
815
+ *
816
+ * To work around this we retry reading the file a handful of times with a delay between each attempt
817
+ *
818
+ * @param {string} path
819
+ * @param {number} tries
820
+ * @returns {string}
821
+ * @throws {Error} If the file is still missing or busy after the specified number of tries
822
+ */ async function readFileWithRetries(path, tries = 5) {
823
+ for(let n = 0; n <= tries; n++){
824
+ try {
825
+ return await _fs.default.promises.readFile(path, "utf8");
826
+ } catch (err) {
827
+ if (n !== tries) {
828
+ if (err.code === "ENOENT" || err.code === "EBUSY") {
829
+ await new Promise((resolve)=>setTimeout(resolve, 10));
830
+ continue;
831
+ }
832
+ }
833
+ throw err;
834
+ }
835
+ }
836
+ }
837
+ // Restore watching any files that are "removed"
838
+ // This can happen when a file is pseudo-atomically replaced (a copy is created, overwritten, the old one is unlinked, and the new one is renamed)
839
+ // TODO: An an optimization we should allow removal when the config changes
840
+ watcher.on("unlink", (file)=>{
841
+ file = (0, _normalizePath.default)(file);
842
+ // Only re-add the file if it's not covered by a dynamic pattern
843
+ if (!_micromatch.default.some([
844
+ file
845
+ ], contentPatterns.dynamic)) {
846
+ watcher.add(file);
847
+ }
848
+ });
849
+ // Some applications such as Visual Studio (but not VS Code)
850
+ // will only fire a rename event for atomic writes and not a change event
851
+ // This is very likely a chokidar bug but it's one we need to work around
852
+ // We treat this as a change event and rebuild the CSS
853
+ watcher.on("raw", (evt, filePath, meta)=>{
854
+ if (evt !== "rename") {
855
+ return;
856
+ }
857
+ let watchedPath = meta.watchedPath;
858
+ // Watched path might be the file itself
859
+ // Or the directory it is in
860
+ filePath = watchedPath.endsWith(filePath) ? watchedPath : _path.default.join(watchedPath, filePath);
861
+ // Skip this event since the files it is for does not match any of the registered content globs
862
+ if (!_micromatch.default.some([
863
+ filePath
864
+ ], contentPatterns.all)) {
865
+ return;
866
+ }
867
+ // Skip since we've already queued a rebuild for this file that hasn't happened yet
868
+ if (pendingRebuilds.has(filePath)) {
869
+ return;
870
+ }
871
+ pendingRebuilds.add(filePath);
872
+ chain = chain.then(async ()=>{
873
+ let content;
874
+ try {
875
+ content = await readFileWithRetries(_path.default.resolve(filePath));
876
+ } finally{
877
+ pendingRebuilds.delete(filePath);
878
+ }
879
+ changedContent.push({
880
+ content,
881
+ extension: _path.default.extname(filePath).slice(1)
882
+ });
883
+ await rebuild(config);
884
+ });
885
+ });
886
+ watcher.on("add", async (file)=>{
685
887
  chain = chain.then(async ()=>{
686
888
  changedContent.push({
687
- content: _fs.default.readFileSync(_path.default.resolve(file), 'utf8'),
889
+ content: _fs.default.readFileSync(_path.default.resolve(file), "utf8"),
688
890
  extension: _path.default.extname(file).slice(1)
689
891
  });
690
- await rebuild(config1);
892
+ await rebuild(config);
691
893
  });
692
894
  });
693
895
  chain = chain.then(()=>{
694
- changedContent.push(...getChangedContent(config1));
695
- return rebuild(config1);
896
+ changedContent.push(...getChangedContent(config));
897
+ return rebuild(config);
696
898
  });
697
899
  }
698
900
  if (shouldWatch) {
699
- /* Abort the watcher if stdin is closed to avoid zombie processes */ process.stdin.on('end', ()=>process.exit(0)
700
- );
901
+ /* Abort the watcher if stdin is closed to avoid zombie processes */ process.stdin.on("end", ()=>process.exit(0));
701
902
  process.stdin.resume();
702
903
  startWatcher();
703
904
  } else {