tailwindcss 3.2.3 → 3.2.5

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 (103) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/README.md +1 -1
  3. package/lib/cli/build/index.js +5 -1
  4. package/lib/cli/build/plugin.js +50 -34
  5. package/lib/cli/build/watching.js +6 -3
  6. package/lib/cli/index.js +231 -10
  7. package/lib/cli/init/index.js +2 -2
  8. package/lib/cli.js +4 -226
  9. package/lib/corePlugins.js +45 -27
  10. package/lib/featureFlags.js +8 -8
  11. package/lib/index.js +4 -46
  12. package/lib/lib/collapseAdjacentRules.js +2 -2
  13. package/lib/lib/collapseDuplicateDeclarations.js +2 -2
  14. package/lib/lib/content.js +16 -16
  15. package/lib/lib/defaultExtractor.js +10 -5
  16. package/lib/lib/detectNesting.js +7 -1
  17. package/lib/lib/evaluateTailwindFunctions.js +4 -4
  18. package/lib/lib/expandApplyAtRules.js +2 -2
  19. package/lib/lib/expandTailwindAtRules.js +35 -9
  20. package/lib/lib/findAtConfigPath.js +3 -3
  21. package/lib/lib/generateRules.js +105 -50
  22. package/lib/lib/offsets.js +88 -1
  23. package/lib/lib/remap-bitfield.js +87 -0
  24. package/lib/lib/resolveDefaultsAtRules.js +4 -4
  25. package/lib/lib/setupContextUtils.js +122 -79
  26. package/lib/lib/setupTrackingContext.js +25 -4
  27. package/lib/lib/sharedState.js +19 -1
  28. package/lib/oxide/cli/build/deps.js +81 -0
  29. package/lib/oxide/cli/build/index.js +47 -0
  30. package/lib/oxide/cli/build/plugin.js +364 -0
  31. package/lib/oxide/cli/build/utils.js +77 -0
  32. package/lib/oxide/cli/build/watching.js +177 -0
  33. package/lib/oxide/cli/help/index.js +70 -0
  34. package/lib/oxide/cli/index.js +220 -0
  35. package/lib/oxide/cli/init/index.js +35 -0
  36. package/lib/oxide/cli.js +5 -0
  37. package/lib/oxide/postcss-plugin.js +2 -0
  38. package/lib/plugin.js +98 -0
  39. package/lib/postcss-plugins/nesting/plugin.js +2 -2
  40. package/lib/util/cloneNodes.js +2 -2
  41. package/lib/util/color.js +20 -6
  42. package/lib/util/createUtilityPlugin.js +2 -2
  43. package/lib/util/dataTypes.js +26 -2
  44. package/lib/util/defaults.js +4 -4
  45. package/lib/util/escapeClassName.js +3 -3
  46. package/lib/util/formatVariantSelector.js +171 -105
  47. package/lib/util/getAllConfigs.js +2 -2
  48. package/lib/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +2 -2
  49. package/lib/util/negateValue.js +2 -2
  50. package/lib/util/normalizeConfig.js +36 -22
  51. package/lib/util/pluginUtils.js +38 -40
  52. package/lib/util/prefixSelector.js +22 -8
  53. package/lib/util/resolveConfig.js +8 -10
  54. package/oxide-node-api-shim/index.js +21 -0
  55. package/oxide-node-api-shim/package.json +5 -0
  56. package/package.json +32 -19
  57. package/peers/index.js +61 -42
  58. package/resolveConfig.d.ts +11 -2
  59. package/scripts/swap-engines.js +40 -0
  60. package/src/cli/build/index.js +6 -2
  61. package/src/cli/build/plugin.js +31 -9
  62. package/src/cli/build/watching.js +6 -3
  63. package/src/cli/index.js +234 -3
  64. package/src/cli.js +4 -220
  65. package/src/corePlugins.js +31 -3
  66. package/src/index.js +4 -46
  67. package/src/lib/content.js +12 -17
  68. package/src/lib/defaultExtractor.js +9 -3
  69. package/src/lib/detectNesting.js +9 -1
  70. package/src/lib/expandTailwindAtRules.js +37 -6
  71. package/src/lib/generateRules.js +90 -28
  72. package/src/lib/offsets.js +104 -1
  73. package/src/lib/remap-bitfield.js +82 -0
  74. package/src/lib/setupContextUtils.js +99 -56
  75. package/src/lib/setupTrackingContext.js +31 -6
  76. package/src/lib/sharedState.js +17 -0
  77. package/src/oxide/cli/build/deps.ts +91 -0
  78. package/src/oxide/cli/build/index.ts +47 -0
  79. package/src/oxide/cli/build/plugin.ts +436 -0
  80. package/src/oxide/cli/build/utils.ts +74 -0
  81. package/src/oxide/cli/build/watching.ts +225 -0
  82. package/src/oxide/cli/help/index.ts +69 -0
  83. package/src/oxide/cli/index.ts +212 -0
  84. package/src/oxide/cli/init/index.ts +32 -0
  85. package/src/oxide/cli.ts +1 -0
  86. package/src/oxide/postcss-plugin.ts +1 -0
  87. package/src/plugin.js +107 -0
  88. package/src/util/color.js +17 -2
  89. package/src/util/dataTypes.js +29 -4
  90. package/src/util/formatVariantSelector.js +215 -122
  91. package/src/util/{isValidArbitraryValue.js → isSyntacticallyValidPropertyValue.js} +1 -1
  92. package/src/util/negateValue.js +1 -1
  93. package/src/util/normalizeConfig.js +18 -0
  94. package/src/util/pluginUtils.js +22 -19
  95. package/src/util/prefixSelector.js +28 -10
  96. package/src/util/resolveConfig.js +0 -2
  97. package/stubs/defaultConfig.stub.js +149 -165
  98. package/types/config.d.ts +7 -2
  99. package/types/generated/default-theme.d.ts +77 -77
  100. package/lib/cli/shared.js +0 -12
  101. package/scripts/install-integrations.js +0 -27
  102. package/scripts/rebuildFixtures.js +0 -68
  103. package/src/cli/shared.js +0 -5
@@ -17,7 +17,7 @@ import { env } from './sharedState'
17
17
  import { toPath } from '../util/toPath'
18
18
  import log from '../util/log'
19
19
  import negateValue from '../util/negateValue'
20
- import isValidArbitraryValue from '../util/isValidArbitraryValue'
20
+ import isSyntacticallyValidPropertyValue from '../util/isSyntacticallyValidPropertyValue'
21
21
  import { generateRules, getClassNameFromSelector } from './generateRules'
22
22
  import { hasContentChanged } from './cacheInvalidation.js'
23
23
  import { Offsets } from './offsets.js'
@@ -54,32 +54,50 @@ function normalizeOptionTypes({ type = 'any', ...options }) {
54
54
  }
55
55
 
56
56
  function parseVariantFormatString(input) {
57
- if (input.includes('{')) {
58
- if (!isBalanced(input)) throw new Error(`Your { and } are unbalanced.`)
59
-
60
- return input
61
- .split(/{(.*)}/gim)
62
- .flatMap((line) => parseVariantFormatString(line))
63
- .filter(Boolean)
64
- }
65
-
66
- return [input.trim()]
67
- }
68
-
69
- function isBalanced(input) {
70
- let count = 0
71
-
72
- for (let char of input) {
73
- if (char === '{') {
74
- count++
57
+ /** @type {string[]} */
58
+ let parts = []
59
+
60
+ // When parsing whitespace around special characters are insignificant
61
+ // However, _inside_ of a variant they could be
62
+ // Because the selector could look like this
63
+ // @media { &[data-name="foo bar"] }
64
+ // This is why we do not skip whitespace
65
+
66
+ let current = ''
67
+ let depth = 0
68
+
69
+ for (let idx = 0; idx < input.length; idx++) {
70
+ let char = input[idx]
71
+
72
+ if (char === '\\') {
73
+ // Escaped characters are not special
74
+ current += '\\' + input[++idx]
75
+ } else if (char === '{') {
76
+ // Nested rule: start
77
+ ++depth
78
+ parts.push(current.trim())
79
+ current = ''
75
80
  } else if (char === '}') {
76
- if (--count < 0) {
77
- return false // unbalanced
81
+ // Nested rule: end
82
+ if (--depth < 0) {
83
+ throw new Error(`Your { and } are unbalanced.`)
78
84
  }
85
+
86
+ parts.push(current.trim())
87
+ current = ''
88
+ } else {
89
+ // Normal character
90
+ current += char
79
91
  }
80
92
  }
81
93
 
82
- return count === 0
94
+ if (current.length > 0) {
95
+ parts.push(current.trim())
96
+ }
97
+
98
+ parts = parts.filter((part) => part !== '')
99
+
100
+ return parts
83
101
  }
84
102
 
85
103
  function insertInto(list, value, { before = [] } = {}) {
@@ -253,25 +271,18 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
253
271
  }
254
272
 
255
273
  function resolveThemeValue(path, defaultValue, opts = {}) {
256
- const [pathRoot, ...subPaths] = toPath(path)
257
- const value = getConfigValue(['theme', pathRoot, ...subPaths], defaultValue)
258
- return transformThemeValue(pathRoot)(value, opts)
274
+ let parts = toPath(path)
275
+ let value = getConfigValue(['theme', ...parts], defaultValue)
276
+ return transformThemeValue(parts[0])(value, opts)
259
277
  }
260
278
 
261
- const theme = Object.assign(
262
- (path, defaultValue = undefined) => resolveThemeValue(path, defaultValue),
263
- {
264
- withAlpha: (path, opacityValue) => resolveThemeValue(path, undefined, { opacityValue }),
265
- }
266
- )
267
-
268
279
  let variantIdentifier = 0
269
280
  let api = {
270
281
  postcss,
271
282
  prefix: applyConfiguredPrefix,
272
283
  e: escapeClassName,
273
284
  config: getConfigValue,
274
- theme,
285
+ theme: resolveThemeValue,
275
286
  corePlugins: (path) => {
276
287
  if (Array.isArray(tailwindConfig.corePlugins)) {
277
288
  return tailwindConfig.corePlugins.includes(path)
@@ -407,7 +418,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
407
418
  }
408
419
  }
409
420
 
410
- if (!isValidArbitraryValue(value)) {
421
+ if (!isSyntacticallyValidPropertyValue(value)) {
411
422
  return []
412
423
  }
413
424
 
@@ -487,7 +498,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
487
498
  }
488
499
  }
489
500
 
490
- if (!isValidArbitraryValue(value)) {
501
+ if (!isSyntacticallyValidPropertyValue(value)) {
491
502
  return []
492
503
  }
493
504
 
@@ -639,6 +650,7 @@ export function getFileModifiedMap(context) {
639
650
 
640
651
  function trackModified(files, fileModifiedMap) {
641
652
  let changed = false
653
+ let mtimesToCommit = new Map()
642
654
 
643
655
  for (let file of files) {
644
656
  if (!file) continue
@@ -659,10 +671,10 @@ function trackModified(files, fileModifiedMap) {
659
671
  changed = true
660
672
  }
661
673
 
662
- fileModifiedMap.set(file, newModified)
674
+ mtimesToCommit.set(file, newModified)
663
675
  }
664
676
 
665
- return changed
677
+ return [changed, mtimesToCommit]
666
678
  }
667
679
 
668
680
  function extractVariantAtRules(node) {
@@ -950,23 +962,35 @@ function registerPlugins(plugins, context) {
950
962
 
951
963
  // Generate a list of strings for autocompletion purposes, e.g.
952
964
  // ['uppercase', 'lowercase', ...]
953
- context.getClassList = function getClassList() {
965
+ context.getClassList = function getClassList(options = {}) {
954
966
  let output = []
955
967
 
956
968
  for (let util of classList) {
957
969
  if (Array.isArray(util)) {
958
- let [utilName, options] = util
970
+ let [utilName, utilOptions] = util
959
971
  let negativeClasses = []
960
972
 
961
- for (let [key, value] of Object.entries(options?.values ?? {})) {
973
+ let modifiers = Object.keys(utilOptions?.modifiers ?? {})
974
+
975
+ if (utilOptions?.types?.some(({ type }) => type === 'color')) {
976
+ modifiers.push(...Object.keys(context.tailwindConfig.theme.opacity ?? {}))
977
+ }
978
+
979
+ let metadata = { modifiers }
980
+ let includeMetadata = options.includeMetadata && modifiers.length > 0
981
+
982
+ for (let [key, value] of Object.entries(utilOptions?.values ?? {})) {
962
983
  // Ignore undefined and null values
963
984
  if (value == null) {
964
985
  continue
965
986
  }
966
987
 
967
- output.push(formatClass(utilName, key))
968
- if (options?.supportsNegativeValues && negateValue(value)) {
969
- negativeClasses.push(formatClass(utilName, `-${key}`))
988
+ let cls = formatClass(utilName, key)
989
+ output.push(includeMetadata ? [cls, metadata] : cls)
990
+
991
+ if (utilOptions?.supportsNegativeValues && negateValue(value)) {
992
+ let cls = formatClass(utilName, `-${key}`)
993
+ negativeClasses.push(includeMetadata ? [cls, metadata] : cls)
970
994
  }
971
995
  }
972
996
 
@@ -1087,20 +1111,38 @@ function registerPlugins(plugins, context) {
1087
1111
  })
1088
1112
  }
1089
1113
 
1090
- let result = formatStrings.map((formatString) =>
1091
- finalizeSelector(formatVariantSelector('&', ...formatString), {
1092
- selector: `.${candidate}`,
1093
- candidate,
1094
- context,
1095
- isArbitraryVariant: !(value in (options.values ?? {})),
1096
- })
1114
+ let isArbitraryVariant = !(value in (options.values ?? {}))
1115
+
1116
+ formatStrings = formatStrings.map((format) =>
1117
+ format.map((str) => ({
1118
+ format: str,
1119
+ isArbitraryVariant,
1120
+ }))
1121
+ )
1122
+
1123
+ manualFormatStrings = manualFormatStrings.map((format) => ({
1124
+ format,
1125
+ isArbitraryVariant,
1126
+ }))
1127
+
1128
+ let opts = {
1129
+ candidate,
1130
+ context,
1131
+ }
1132
+
1133
+ let result = formatStrings.map((formats) =>
1134
+ finalizeSelector(`.${candidate}`, formatVariantSelector(formats, opts), opts)
1097
1135
  .replace(`.${candidate}`, '&')
1098
1136
  .replace('{ & }', '')
1099
1137
  .trim()
1100
1138
  )
1101
1139
 
1102
1140
  if (manualFormatStrings.length > 0) {
1103
- result.push(formatVariantSelector('&', ...manualFormatStrings))
1141
+ result.push(
1142
+ formatVariantSelector(manualFormatStrings, opts)
1143
+ .toString()
1144
+ .replace(`.${candidate}`, '&')
1145
+ )
1104
1146
  }
1105
1147
 
1106
1148
  return result
@@ -1165,7 +1207,8 @@ export function createContext(tailwindConfig, changedContent = [], root = postcs
1165
1207
  candidateRuleCache: new Map(),
1166
1208
  classCache: new Map(),
1167
1209
  applyClassCache: new Map(),
1168
- notClassCache: new Set(),
1210
+ // Seed the not class cache with the blocklist (which is only strings)
1211
+ notClassCache: new Set(tailwindConfig.blocklist ?? []),
1169
1212
  postCssNodeCache: new Map(),
1170
1213
  candidateRuleMap: new Map(),
1171
1214
  tailwindConfig,
@@ -1218,12 +1261,12 @@ export function getContext(
1218
1261
  // If there's already a context in the cache and we don't need to
1219
1262
  // reset the context, return the cached context.
1220
1263
  if (existingContext) {
1221
- let contextDependenciesChanged = trackModified(
1264
+ let [contextDependenciesChanged, mtimesToCommit] = trackModified(
1222
1265
  [...contextDependencies],
1223
1266
  getFileModifiedMap(existingContext)
1224
1267
  )
1225
1268
  if (!contextDependenciesChanged && !cssDidChange) {
1226
- return [existingContext, false]
1269
+ return [existingContext, false, mtimesToCommit]
1227
1270
  }
1228
1271
  }
1229
1272
 
@@ -1258,7 +1301,7 @@ export function getContext(
1258
1301
  userConfigPath,
1259
1302
  })
1260
1303
 
1261
- trackModified([...contextDependencies], getFileModifiedMap(context))
1304
+ let [, mtimesToCommit] = trackModified([...contextDependencies], getFileModifiedMap(context))
1262
1305
 
1263
1306
  // ---
1264
1307
 
@@ -1273,5 +1316,5 @@ export function getContext(
1273
1316
 
1274
1317
  contextSourcesMap.get(context).add(sourcePath)
1275
1318
 
1276
- return [context, true]
1319
+ return [context, true, mtimesToCommit]
1277
1320
  }
@@ -1,3 +1,5 @@
1
+ // @ts-check
2
+
1
3
  import fs from 'fs'
2
4
  import LRU from 'quick-lru'
3
5
 
@@ -101,7 +103,7 @@ export default function setupTrackingContext(configOrPath) {
101
103
  }
102
104
  }
103
105
 
104
- let [context] = getContext(
106
+ let [context, , mTimesToCommit] = getContext(
105
107
  root,
106
108
  result,
107
109
  tailwindConfig,
@@ -110,6 +112,8 @@ export default function setupTrackingContext(configOrPath) {
110
112
  contextDependencies
111
113
  )
112
114
 
115
+ let fileModifiedMap = getFileModifiedMap(context)
116
+
113
117
  let candidateFiles = getCandidateFiles(context, tailwindConfig)
114
118
 
115
119
  // If there are no @tailwind or @apply rules, we don't consider this CSS file or it's
@@ -118,8 +122,6 @@ export default function setupTrackingContext(configOrPath) {
118
122
  // because it's impossible for a layer in one file to end up in the actual @tailwind rule
119
123
  // in another file since independent sources are effectively isolated.
120
124
  if (tailwindDirectives.size > 0) {
121
- let fileModifiedMap = getFileModifiedMap(context)
122
-
123
125
  // Add template paths as postcss dependencies.
124
126
  for (let contentPath of candidateFiles) {
125
127
  for (let dependency of parseDependency(contentPath)) {
@@ -127,12 +129,28 @@ export default function setupTrackingContext(configOrPath) {
127
129
  }
128
130
  }
129
131
 
130
- for (let changedContent of resolvedChangedContent(
132
+ let [changedContent, contentMTimesToCommit] = resolvedChangedContent(
131
133
  context,
132
134
  candidateFiles,
133
135
  fileModifiedMap
134
- )) {
135
- context.changedContent.push(changedContent)
136
+ )
137
+
138
+ for (let content of changedContent) {
139
+ context.changedContent.push(content)
140
+ }
141
+
142
+ // Add the mtimes of the content files to the commit list
143
+ // We can overwrite the existing values because unconditionally
144
+ // This is because:
145
+ // 1. Most of the files here won't be in the map yet
146
+ // 2. If they are that means it's a context dependency
147
+ // and we're reading this after the context. This means
148
+ // that the mtime we just read is strictly >= the context
149
+ // mtime. Unless the user / os is doing something weird
150
+ // in which the mtime would be going backwards. If that
151
+ // happens there's already going to be problems.
152
+ for (let [path, mtime] of contentMTimesToCommit.entries()) {
153
+ mTimesToCommit.set(path, mtime)
136
154
  }
137
155
  }
138
156
 
@@ -140,6 +158,13 @@ export default function setupTrackingContext(configOrPath) {
140
158
  registerDependency({ type: 'dependency', file })
141
159
  }
142
160
 
161
+ // "commit" the new modified time for all context deps
162
+ // We do this here because we want content tracking to
163
+ // read the "old" mtime even when it's a context dependency.
164
+ for (let [path, mtime] of mTimesToCommit.entries()) {
165
+ fileModifiedMap.set(path, mtime)
166
+ }
167
+
143
168
  return context
144
169
  }
145
170
  }
@@ -1,6 +1,11 @@
1
+ import pkg from '../../package.json'
2
+ let OXIDE_DEFAULT_ENABLED = pkg.tailwindcss.engine === 'oxide'
3
+
1
4
  export const env = {
2
5
  NODE_ENV: process.env.NODE_ENV,
3
6
  DEBUG: resolveDebug(process.env.DEBUG),
7
+ ENGINE: pkg.tailwindcss.engine,
8
+ OXIDE: resolveBoolean(process.env.OXIDE, OXIDE_DEFAULT_ENABLED),
4
9
  }
5
10
  export const contextMap = new Map()
6
11
  export const configContextMap = new Map()
@@ -10,6 +15,18 @@ export const NOT_ON_DEMAND = new String('*')
10
15
 
11
16
  export const NONE = Symbol('__NONE__')
12
17
 
18
+ function resolveBoolean(value, defaultValue) {
19
+ if (value === undefined) {
20
+ return defaultValue
21
+ }
22
+
23
+ if (value === '0' || value === 'false') {
24
+ return false
25
+ }
26
+
27
+ return true
28
+ }
29
+
13
30
  export function resolveDebug(debug) {
14
31
  if (debug === undefined) {
15
32
  return false
@@ -0,0 +1,91 @@
1
+ import packageJson from '../../../../package.json'
2
+ import browserslist from 'browserslist'
3
+ import { Result } from 'postcss'
4
+
5
+ import {
6
+ // @ts-ignore
7
+ lazyPostcss,
8
+
9
+ // @ts-ignore
10
+ lazyPostcssImport,
11
+
12
+ // @ts-ignore
13
+ lazyCssnano,
14
+
15
+ // @ts-ignore
16
+ } from '../../../../peers/index'
17
+
18
+ export function lazyLightningCss() {
19
+ // TODO: Make this lazy/bundled
20
+ return require('lightningcss')
21
+ }
22
+
23
+ let lightningCss
24
+
25
+ function loadLightningCss() {
26
+ if (lightningCss) {
27
+ return lightningCss
28
+ }
29
+
30
+ // Try to load a local version first
31
+ try {
32
+ return (lightningCss = require('lightningcss'))
33
+ } catch {}
34
+
35
+ return (lightningCss = lazyLightningCss())
36
+ }
37
+
38
+ export async function lightningcss(shouldMinify: boolean, result: Result) {
39
+ let css = loadLightningCss()
40
+
41
+ try {
42
+ let transformed = css.transform({
43
+ filename: result.opts.from || 'input.css',
44
+ code: Buffer.from(result.css, 'utf-8'),
45
+ minify: shouldMinify,
46
+ sourceMap: !!result.map,
47
+ inputSourceMap: result.map ? result.map.toString() : undefined,
48
+ targets: css.browserslistToTargets(browserslist(packageJson.browserslist)),
49
+ drafts: {
50
+ nesting: true,
51
+ },
52
+ })
53
+
54
+ return Object.assign(result, {
55
+ css: transformed.code.toString('utf8'),
56
+ map: result.map
57
+ ? Object.assign(result.map, {
58
+ toString() {
59
+ return transformed.map.toString()
60
+ },
61
+ })
62
+ : result.map,
63
+ })
64
+ } catch (err) {
65
+ console.error('Unable to use Lightning CSS. Using raw version instead.')
66
+ console.error(err)
67
+
68
+ return result
69
+ }
70
+ }
71
+
72
+ /**
73
+ * @returns {import('postcss')}
74
+ */
75
+ export function loadPostcss() {
76
+ // Try to load a local `postcss` version first
77
+ try {
78
+ return require('postcss')
79
+ } catch {}
80
+
81
+ return lazyPostcss()
82
+ }
83
+
84
+ export function loadPostcssImport() {
85
+ // Try to load a local `postcss-import` version first
86
+ try {
87
+ return require('postcss-import')
88
+ } catch {}
89
+
90
+ return lazyPostcssImport()
91
+ }
@@ -0,0 +1,47 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+ import { createProcessor } from './plugin'
4
+
5
+ export async function build(args, configs) {
6
+ let input = args['--input']
7
+ let shouldWatch = args['--watch']
8
+
9
+ // TODO: Deprecate this in future versions
10
+ if (!input && args['_'][1]) {
11
+ console.error('[deprecation] Running tailwindcss without -i, please provide an input file.')
12
+ input = args['--input'] = args['_'][1]
13
+ }
14
+
15
+ if (input && input !== '-' && !fs.existsSync((input = path.resolve(input)))) {
16
+ console.error(`Specified input file ${args['--input']} does not exist.`)
17
+ process.exit(9)
18
+ }
19
+
20
+ if (args['--config'] && !fs.existsSync((args['--config'] = path.resolve(args['--config'])))) {
21
+ console.error(`Specified config file ${args['--config']} does not exist.`)
22
+ process.exit(9)
23
+ }
24
+
25
+ // TODO: Reference the @config path here if exists
26
+ let configPath = args['--config']
27
+ ? args['--config']
28
+ : ((defaultPath) => (fs.existsSync(defaultPath) ? defaultPath : null))(
29
+ path.resolve(`./${configs.tailwind}`)
30
+ )
31
+
32
+ let processor = await createProcessor(args, configPath)
33
+
34
+ if (shouldWatch) {
35
+ // Abort the watcher if stdin is closed to avoid zombie processes
36
+ // You can disable this behavior with --watch=always
37
+ if (args['--watch'] !== 'always') {
38
+ process.stdin.on('end', () => process.exit(0))
39
+ }
40
+
41
+ process.stdin.resume()
42
+
43
+ await processor.watch()
44
+ } else {
45
+ await processor.build()
46
+ }
47
+ }