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
@@ -1,3 +1,12 @@
1
- import type { Config } from './types/config'
2
- declare function resolveConfig(config: Config): Config
1
+ import type { Config, ResolvableTo } from './types/config'
2
+
3
+ type UnwrapResolvables<T> = {
4
+ [K in keyof T]: T[K] extends ResolvableTo<infer R> ? R : T[K]
5
+ }
6
+
7
+ type ResolvedConfig<T extends Config> = Omit<T, 'theme'> & {
8
+ theme: UnwrapResolvables<T['theme']>
9
+ }
10
+
11
+ declare function resolveConfig<T extends Config>(config: T): ResolvedConfig<T>
3
12
  export = resolveConfig
@@ -0,0 +1,40 @@
1
+ let fs = require('fs')
2
+ let path = require('path')
3
+
4
+ let engines = {
5
+ stable: {
6
+ files: [
7
+ path.resolve(__dirname, '..', 'package.stable.json'),
8
+ path.resolve(__dirname, '..', 'package-lock.stable.json'),
9
+ ],
10
+ },
11
+ oxide: {
12
+ files: [
13
+ path.resolve(__dirname, '..', 'package.oxide.json'),
14
+ path.resolve(__dirname, '..', 'package-lock.oxide.json'),
15
+ ],
16
+ },
17
+ }
18
+
19
+ // Find out what the current engine is that we are using:
20
+ let [otherEngine, info] = Object.entries(engines).find(([, info]) =>
21
+ info.files.every((file) => fs.existsSync(file))
22
+ )
23
+ let currentEngine = otherEngine === 'oxide' ? 'stable' : 'oxide'
24
+
25
+ console.log(`Current engine: \`${currentEngine}\`, swapping to \`${otherEngine}\``)
26
+
27
+ // Swap the engines
28
+ for (let file of info.files) {
29
+ fs.renameSync(
30
+ file.replace(`.${otherEngine}`, ''),
31
+ file.replace(`.${otherEngine}`, `.${currentEngine}`)
32
+ )
33
+ }
34
+ for (let file of engines[otherEngine].files) {
35
+ fs.renameSync(file, file.replace(`.${otherEngine}`, ''))
36
+ }
37
+
38
+ console.log(
39
+ 'Engines have been swapped. Make sure to run `npm install` to update your dependencies.'
40
+ )
@@ -2,9 +2,10 @@
2
2
 
3
3
  import fs from 'fs'
4
4
  import path from 'path'
5
+ import { resolveDefaultConfigPath } from '../../util/resolveConfigPath.js'
5
6
  import { createProcessor } from './plugin.js'
6
7
 
7
- export async function build(args, configs) {
8
+ export async function build(args) {
8
9
  let input = args['--input']
9
10
  let shouldWatch = args['--watch']
10
11
 
@@ -25,21 +26,24 @@ export async function build(args, configs) {
25
26
  }
26
27
 
27
28
  // TODO: Reference the @config path here if exists
28
- let configPath = args['--config']
29
- ? args['--config']
30
- : ((defaultPath) => (fs.existsSync(defaultPath) ? defaultPath : null))(
31
- path.resolve(`./${configs.tailwind}`)
32
- )
29
+ let configPath = args['--config'] ? args['--config'] : resolveDefaultConfigPath()
33
30
 
34
31
  let processor = await createProcessor(args, configPath)
35
32
 
36
33
  if (shouldWatch) {
37
- /* Abort the watcher if stdin is closed to avoid zombie processes */
38
- process.stdin.on('end', () => process.exit(0))
34
+ // Abort the watcher if stdin is closed to avoid zombie processes
35
+ // You can disable this behavior with --watch=always
36
+ if (args['--watch'] !== 'always') {
37
+ process.stdin.on('end', () => process.exit(0))
38
+ }
39
+
39
40
  process.stdin.resume()
40
41
 
41
42
  await processor.watch()
42
43
  } else {
43
- await processor.build()
44
+ await processor.build().catch((e) => {
45
+ console.error(e)
46
+ process.exit(1)
47
+ })
44
48
  }
45
49
  }
@@ -10,14 +10,15 @@ import loadOptions from 'postcss-load-config/src/options' // Little bit scary, l
10
10
  import tailwind from '../../processTailwindFeatures'
11
11
  import { loadAutoprefixer, loadCssNano, loadPostcss, loadPostcssImport } from './deps'
12
12
  import { formatNodes, drainStdin, outputFile } from './utils'
13
- import { env } from '../shared'
13
+ import { env } from '../../lib/sharedState'
14
14
  import resolveConfig from '../../../resolveConfig.js'
15
- import getModuleDependencies from '../../lib/getModuleDependencies.js'
16
15
  import { parseCandidateFiles } from '../../lib/content.js'
17
16
  import { createWatcher } from './watching.js'
18
17
  import fastGlob from 'fast-glob'
19
18
  import { findAtConfigPath } from '../../lib/findAtConfigPath.js'
20
19
  import log from '../../util/log'
20
+ import { loadConfig } from '../../lib/load-config'
21
+ import getModuleDependencies from '../../lib/getModuleDependencies'
21
22
 
22
23
  /**
23
24
  *
@@ -117,7 +118,9 @@ let state = {
117
118
  /** @type {{content: string, extension: string}[]} */
118
119
  changedContent: [],
119
120
 
120
- configDependencies: new Set(),
121
+ /** @type {ReturnType<typeof load> | null} */
122
+ configBag: null,
123
+
121
124
  contextDependencies: new Set(),
122
125
 
123
126
  /** @type {import('../../lib/content.js').ContentPath[]} */
@@ -142,37 +145,35 @@ let state = {
142
145
 
143
146
  loadConfig(configPath, content) {
144
147
  if (this.watcher && configPath) {
145
- this.refreshConfigDependencies(configPath)
148
+ this.refreshConfigDependencies()
146
149
  }
147
150
 
148
- let config = configPath ? require(configPath) : {}
151
+ let config = loadConfig(configPath)
152
+ let dependencies = getModuleDependencies(configPath)
153
+ this.configBag = {
154
+ config,
155
+ dependencies,
156
+ dispose() {
157
+ for (let file of dependencies) {
158
+ delete require.cache[require.resolve(file)]
159
+ }
160
+ },
161
+ }
149
162
 
150
163
  // @ts-ignore
151
- config = resolveConfig(config, { content: { files: [] } })
164
+ this.configBag.config = resolveConfig(this.configBag.config, { content: { files: [] } })
152
165
 
153
166
  // Override content files if `--content` has been passed explicitly
154
167
  if (content?.length > 0) {
155
- config.content.files = content
168
+ this.configBag.config.content.files = content
156
169
  }
157
170
 
158
- return config
171
+ return this.configBag.config
159
172
  },
160
173
 
161
- refreshConfigDependencies(configPath) {
174
+ refreshConfigDependencies() {
162
175
  env.DEBUG && console.time('Module dependencies')
163
-
164
- for (let file of this.configDependencies) {
165
- delete require.cache[require.resolve(file)]
166
- }
167
-
168
- if (configPath) {
169
- let deps = getModuleDependencies(configPath).map(({ file }) => file)
170
-
171
- for (let dependency of deps) {
172
- this.configDependencies.add(dependency)
173
- }
174
- }
175
-
176
+ this.configBag?.dispose()
176
177
  env.DEBUG && console.timeEnd('Module dependencies')
177
178
  },
178
179
 
@@ -184,10 +185,17 @@ let state = {
184
185
  let files = fastGlob.sync(this.contentPatterns.all)
185
186
 
186
187
  for (let file of files) {
187
- content.push({
188
- content: fs.readFileSync(path.resolve(file), 'utf8'),
189
- extension: path.extname(file).slice(1),
190
- })
188
+ if (__OXIDE__) {
189
+ content.push({
190
+ file,
191
+ extension: path.extname(file).slice(1),
192
+ })
193
+ } else {
194
+ content.push({
195
+ content: fs.readFileSync(path.resolve(file), 'utf8'),
196
+ extension: path.extname(file).slice(1),
197
+ })
198
+ }
191
199
  }
192
200
 
193
201
  // Resolve raw content in the tailwind config
@@ -234,11 +242,9 @@ let state = {
234
242
  env.DEBUG && console.timeEnd('Watch new files')
235
243
  }
236
244
 
237
- env.DEBUG && console.time('Reading content files')
238
245
  for (let file of this.readContentPaths()) {
239
246
  this.context.changedContent.push(file)
240
247
  }
241
- env.DEBUG && console.timeEnd('Reading content files')
242
248
 
243
249
  return this.context
244
250
  },
@@ -355,8 +361,8 @@ export async function createProcessor(args, cliConfigPath) {
355
361
  }
356
362
 
357
363
  return Promise.all([
358
- outputFile(output, result.css),
359
- result.map && outputFile(output + '.map', result.map.toString()),
364
+ outputFile(result.opts.to, result.css),
365
+ result.map && outputFile(result.opts.to + '.map', result.map.toString()),
360
366
  ])
361
367
  })
362
368
  .then(() => {
@@ -378,7 +384,11 @@ export async function createProcessor(args, cliConfigPath) {
378
384
  // The watcher will start watching the imported CSS files and will be
379
385
  // resilient to future errors.
380
386
 
381
- console.error(err)
387
+ if (state.watcher) {
388
+ console.error(err)
389
+ } else {
390
+ return Promise.reject(err)
391
+ }
382
392
  }
383
393
  )
384
394
  }
@@ -411,7 +421,7 @@ export async function createProcessor(args, cliConfigPath) {
411
421
  async rebuild(changes) {
412
422
  let needsNewContext = changes.some((change) => {
413
423
  return (
414
- state.configDependencies.has(change.file) ||
424
+ state.configBag?.dependencies.has(change.file) ||
415
425
  state.contextDependencies.has(change.file)
416
426
  )
417
427
  })
@@ -89,7 +89,9 @@ export function createWatcher(args, { state, rebuild }) {
89
89
  // Resolve the promise even when the rebuild fails
90
90
  return rebuild(changes).then(
91
91
  () => {},
92
- () => {}
92
+ (e) => {
93
+ console.error(e.toString())
94
+ }
93
95
  )
94
96
  }
95
97
 
@@ -220,7 +222,7 @@ export function createWatcher(args, { state, rebuild }) {
220
222
 
221
223
  refreshWatchedFiles() {
222
224
  watcher.add(Array.from(state.contextDependencies))
223
- watcher.add(Array.from(state.configDependencies))
225
+ watcher.add(Array.from(state.configBag.dependencies))
224
226
  watcher.add(state.contentPatterns.all)
225
227
  },
226
228
  }
package/src/cli/index.js CHANGED
@@ -1,3 +1,216 @@
1
- export * from './build'
2
- export * from './config'
3
- export * from './content'
1
+ #!/usr/bin/env node
2
+
3
+ import path from 'path'
4
+ import arg from 'arg'
5
+ import fs from 'fs'
6
+
7
+ import { build } from './build'
8
+ import { help } from './help'
9
+ import { init } from './init'
10
+
11
+ function oneOf(...options) {
12
+ return Object.assign(
13
+ (value = true) => {
14
+ for (let option of options) {
15
+ let parsed = option(value)
16
+ if (parsed === value) {
17
+ return parsed
18
+ }
19
+ }
20
+
21
+ throw new Error('...')
22
+ },
23
+ { manualParsing: true }
24
+ )
25
+ }
26
+
27
+ let commands = {
28
+ init: {
29
+ run: init,
30
+ args: {
31
+ '--esm': { type: Boolean, description: `Initialize configuration file as ESM` },
32
+ '--ts': { type: Boolean, description: `Initialize configuration file as TypeScript` },
33
+ '--postcss': { type: Boolean, description: `Initialize a \`postcss.config.js\` file` },
34
+ '--full': {
35
+ type: Boolean,
36
+ description: `Include the default values for all options in the generated configuration file`,
37
+ },
38
+ '-f': '--full',
39
+ '-p': '--postcss',
40
+ },
41
+ },
42
+ build: {
43
+ run: build,
44
+ args: {
45
+ '--input': { type: String, description: 'Input file' },
46
+ '--output': { type: String, description: 'Output file' },
47
+ '--watch': {
48
+ type: oneOf(String, Boolean),
49
+ description: 'Watch for changes and rebuild as needed',
50
+ },
51
+ '--poll': {
52
+ type: Boolean,
53
+ description: 'Use polling instead of filesystem events when watching',
54
+ },
55
+ '--content': {
56
+ type: String,
57
+ description: 'Content paths to use for removing unused classes',
58
+ },
59
+ '--purge': {
60
+ type: String,
61
+ deprecated: true,
62
+ },
63
+ '--postcss': {
64
+ type: oneOf(String, Boolean),
65
+ description: 'Load custom PostCSS configuration',
66
+ },
67
+ '--minify': { type: Boolean, description: 'Minify the output' },
68
+ '--config': {
69
+ type: String,
70
+ description: 'Path to a custom config file',
71
+ },
72
+ '--no-autoprefixer': {
73
+ type: Boolean,
74
+ description: 'Disable autoprefixer',
75
+ },
76
+ '-c': '--config',
77
+ '-i': '--input',
78
+ '-o': '--output',
79
+ '-m': '--minify',
80
+ '-w': '--watch',
81
+ '-p': '--poll',
82
+ },
83
+ },
84
+ }
85
+
86
+ let sharedFlags = {
87
+ '--help': { type: Boolean, description: 'Display usage information' },
88
+ '-h': '--help',
89
+ }
90
+
91
+ if (
92
+ process.stdout.isTTY /* Detect redirecting output to a file */ &&
93
+ (process.argv[2] === undefined ||
94
+ process.argv.slice(2).every((flag) => sharedFlags[flag] !== undefined))
95
+ ) {
96
+ help({
97
+ usage: [
98
+ 'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]',
99
+ 'tailwindcss init [--full] [--postcss] [options...]',
100
+ ],
101
+ commands: Object.keys(commands)
102
+ .filter((command) => command !== 'build')
103
+ .map((command) => `${command} [options]`),
104
+ options: { ...commands.build.args, ...sharedFlags },
105
+ })
106
+ process.exit(0)
107
+ }
108
+
109
+ let command = ((arg = '') => (arg.startsWith('-') ? undefined : arg))(process.argv[2]) || 'build'
110
+
111
+ if (commands[command] === undefined) {
112
+ if (fs.existsSync(path.resolve(command))) {
113
+ // TODO: Deprecate this in future versions
114
+ // Check if non-existing command, might be a file.
115
+ command = 'build'
116
+ } else {
117
+ help({
118
+ message: `Invalid command: ${command}`,
119
+ usage: ['tailwindcss <command> [options]'],
120
+ commands: Object.keys(commands)
121
+ .filter((command) => command !== 'build')
122
+ .map((command) => `${command} [options]`),
123
+ options: sharedFlags,
124
+ })
125
+ process.exit(1)
126
+ }
127
+ }
128
+
129
+ // Execute command
130
+ let { args: flags, run } = commands[command]
131
+ let args = (() => {
132
+ try {
133
+ let result = arg(
134
+ Object.fromEntries(
135
+ Object.entries({ ...flags, ...sharedFlags })
136
+ .filter(([_key, value]) => !value?.type?.manualParsing)
137
+ .map(([key, value]) => [key, typeof value === 'object' ? value.type : value])
138
+ ),
139
+ { permissive: true }
140
+ )
141
+
142
+ // Manual parsing of flags to allow for special flags like oneOf(Boolean, String)
143
+ for (let i = result['_'].length - 1; i >= 0; --i) {
144
+ let flag = result['_'][i]
145
+ if (!flag.startsWith('-')) continue
146
+
147
+ let [flagName, flagValue] = flag.split('=')
148
+ let handler = flags[flagName]
149
+
150
+ // Resolve flagName & handler
151
+ while (typeof handler === 'string') {
152
+ flagName = handler
153
+ handler = flags[handler]
154
+ }
155
+
156
+ if (!handler) continue
157
+
158
+ let args = []
159
+ let offset = i + 1
160
+
161
+ // --flag value syntax was used so we need to pull `value` from `args`
162
+ if (flagValue === undefined) {
163
+ // Parse args for current flag
164
+ while (result['_'][offset] && !result['_'][offset].startsWith('-')) {
165
+ args.push(result['_'][offset++])
166
+ }
167
+
168
+ // Cleanup manually parsed flags + args
169
+ result['_'].splice(i, 1 + args.length)
170
+
171
+ // No args were provided, use default value defined in handler
172
+ // One arg was provided, use that directly
173
+ // Multiple args were provided so pass them all in an array
174
+ flagValue = args.length === 0 ? undefined : args.length === 1 ? args[0] : args
175
+ } else {
176
+ // Remove the whole flag from the args array
177
+ result['_'].splice(i, 1)
178
+ }
179
+
180
+ // Set the resolved value in the `result` object
181
+ result[flagName] = handler.type(flagValue, flagName)
182
+ }
183
+
184
+ // Ensure that the `command` is always the first argument in the `args`.
185
+ // This is important so that we don't have to check if a default command
186
+ // (build) was used or not from within each plugin.
187
+ //
188
+ // E.g.: tailwindcss input.css -> _: ['build', 'input.css']
189
+ // E.g.: tailwindcss build input.css -> _: ['build', 'input.css']
190
+ if (result['_'][0] !== command) {
191
+ result['_'].unshift(command)
192
+ }
193
+
194
+ return result
195
+ } catch (err) {
196
+ if (err.code === 'ARG_UNKNOWN_OPTION') {
197
+ help({
198
+ message: err.message,
199
+ usage: ['tailwindcss <command> [options]'],
200
+ options: sharedFlags,
201
+ })
202
+ process.exit(1)
203
+ }
204
+ throw err
205
+ }
206
+ })()
207
+
208
+ if (args['--help']) {
209
+ help({
210
+ options: { ...flags, ...sharedFlags },
211
+ usage: [`tailwindcss ${command} [options]`],
212
+ })
213
+ process.exit(0)
214
+ }
215
+
216
+ run(args)
@@ -3,22 +3,49 @@
3
3
  import fs from 'fs'
4
4
  import path from 'path'
5
5
 
6
- export function init(args, configs) {
6
+ function isESM() {
7
+ const pkgPath = path.resolve('./package.json')
8
+
9
+ try {
10
+ let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
11
+ return pkg.type && pkg.type === 'module'
12
+ } catch (err) {
13
+ return false
14
+ }
15
+ }
16
+
17
+ export function init(args) {
7
18
  let messages = []
8
19
 
9
- let tailwindConfigLocation = path.resolve(args['_'][1] ?? `./${configs.tailwind}`)
20
+ let isProjectESM = args['--ts'] || args['--esm'] || isESM()
21
+ let syntax = args['--ts'] ? 'ts' : isProjectESM ? 'js' : 'cjs'
22
+ let extension = args['--ts'] ? 'ts' : 'js'
23
+
24
+ let tailwindConfigLocation = path.resolve(args['_'][1] ?? `./tailwind.config.${extension}`)
25
+
10
26
  if (fs.existsSync(tailwindConfigLocation)) {
11
27
  messages.push(`${path.basename(tailwindConfigLocation)} already exists.`)
12
28
  } else {
13
- let stubFile = fs.readFileSync(
29
+ let stubContentsFile = fs.readFileSync(
14
30
  args['--full']
15
- ? path.resolve(__dirname, '../../../stubs/defaultConfig.stub.js')
16
- : path.resolve(__dirname, '../../../stubs/simpleConfig.stub.js'),
31
+ ? path.resolve(__dirname, '../../../stubs/config.full.js')
32
+ : path.resolve(__dirname, '../../../stubs/config.simple.js'),
33
+ 'utf8'
34
+ )
35
+
36
+ let stubFile = fs.readFileSync(
37
+ path.resolve(__dirname, `../../../stubs/tailwind.config.${syntax}`),
17
38
  'utf8'
18
39
  )
19
40
 
20
41
  // Change colors import
21
- stubFile = stubFile.replace('../colors', 'tailwindcss/colors')
42
+ stubContentsFile = stubContentsFile.replace('../colors', 'tailwindcss/colors')
43
+
44
+ // Replace contents of {ts,js,cjs} file with the stub {simple,full}.
45
+ stubFile =
46
+ stubFile
47
+ .replace('__CONFIG__', stubContentsFile.replace('module.exports =', '').trim())
48
+ .trim() + '\n\n'
22
49
 
23
50
  fs.writeFileSync(tailwindConfigLocation, stubFile, 'utf8')
24
51
 
@@ -26,12 +53,14 @@ export function init(args, configs) {
26
53
  }
27
54
 
28
55
  if (args['--postcss']) {
29
- let postcssConfigLocation = path.resolve(`./${configs.postcss}`)
56
+ let postcssConfigLocation = path.resolve('./postcss.config.js')
30
57
  if (fs.existsSync(postcssConfigLocation)) {
31
58
  messages.push(`${path.basename(postcssConfigLocation)} already exists.`)
32
59
  } else {
33
60
  let stubFile = fs.readFileSync(
34
- path.resolve(__dirname, '../../../stubs/defaultPostCssConfig.stub.js'),
61
+ isProjectESM
62
+ ? path.resolve(__dirname, '../../../stubs/postcss.config.js')
63
+ : path.resolve(__dirname, '../../../stubs/postcss.config.cjs'),
35
64
  'utf8'
36
65
  )
37
66