tailwindcss 3.2.7 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +44 -8
  2. package/lib/cli/build/index.js +7 -3
  3. package/lib/cli/build/plugin.js +28 -19
  4. package/lib/cli/build/watching.js +4 -2
  5. package/lib/cli/index.js +12 -21
  6. package/lib/cli/init/index.js +21 -6
  7. package/lib/corePluginList.js +4 -0
  8. package/lib/corePlugins.js +282 -26
  9. package/lib/css/preflight.css +2 -0
  10. package/lib/featureFlags.js +8 -1
  11. package/lib/lib/expandApplyAtRules.js +2 -1
  12. package/lib/lib/generateRules.js +14 -10
  13. package/lib/lib/getModuleDependencies.js +79 -33
  14. package/lib/lib/load-config.js +36 -0
  15. package/lib/lib/setupContextUtils.js +10 -2
  16. package/lib/lib/setupTrackingContext.js +4 -4
  17. package/lib/oxide/cli/build/index.js +7 -3
  18. package/lib/oxide/cli/build/plugin.js +27 -18
  19. package/lib/oxide/cli/build/watching.js +1 -1
  20. package/lib/oxide/cli/index.js +10 -16
  21. package/lib/oxide/cli/init/index.js +19 -4
  22. package/lib/public/colors.js +44 -22
  23. package/lib/public/default-config.js +2 -2
  24. package/lib/public/default-theme.js +2 -2
  25. package/lib/public/load-config.js +10 -0
  26. package/lib/util/applyImportantSelector.js +22 -0
  27. package/lib/util/dataTypes.js +3 -0
  28. package/lib/util/getAllConfigs.js +2 -2
  29. package/lib/util/normalizeConfig.js +16 -3
  30. package/lib/util/pluginUtils.js +9 -2
  31. package/lib/util/resolveConfigPath.js +19 -7
  32. package/lib/util/splitAtTopLevelOnly.js +7 -1
  33. package/loadConfig.d.ts +4 -0
  34. package/loadConfig.js +2 -0
  35. package/package.json +5 -4
  36. package/src/cli/build/index.js +7 -7
  37. package/src/cli/build/plugin.js +28 -23
  38. package/src/cli/build/watching.js +4 -2
  39. package/src/cli/index.js +8 -26
  40. package/src/cli/init/index.js +37 -8
  41. package/src/corePluginList.js +1 -1
  42. package/src/corePlugins.js +184 -27
  43. package/src/css/preflight.css +2 -0
  44. package/src/featureFlags.js +7 -0
  45. package/src/lib/expandApplyAtRules.js +2 -1
  46. package/src/lib/generateRules.js +15 -5
  47. package/src/lib/getModuleDependencies.js +70 -30
  48. package/src/lib/load-config.ts +27 -0
  49. package/src/lib/setupContextUtils.js +9 -2
  50. package/src/lib/setupTrackingContext.js +4 -4
  51. package/src/oxide/cli/build/index.ts +7 -7
  52. package/src/oxide/cli/build/plugin.ts +28 -22
  53. package/src/oxide/cli/build/watching.ts +1 -1
  54. package/src/oxide/cli/index.ts +7 -15
  55. package/src/oxide/cli/init/index.ts +34 -7
  56. package/src/public/colors.js +22 -0
  57. package/src/public/default-config.js +1 -1
  58. package/src/public/default-theme.js +2 -2
  59. package/src/public/load-config.js +2 -0
  60. package/src/util/applyImportantSelector.js +19 -0
  61. package/src/util/dataTypes.js +4 -0
  62. package/src/util/getAllConfigs.js +2 -2
  63. package/src/util/normalizeConfig.js +19 -1
  64. package/src/util/pluginUtils.js +10 -2
  65. package/src/util/resolveConfigPath.js +12 -1
  66. package/src/util/splitAtTopLevelOnly.js +8 -1
  67. package/stubs/.gitignore +1 -0
  68. package/stubs/.prettierrc.json +6 -0
  69. package/stubs/{defaultConfig.stub.js → config.full.js} +36 -1
  70. package/stubs/{simpleConfig.stub.js → config.simple.js} +0 -1
  71. package/stubs/postcss.config.js +6 -0
  72. package/stubs/tailwind.config.cjs +2 -0
  73. package/stubs/tailwind.config.js +2 -0
  74. package/stubs/tailwind.config.ts +3 -0
  75. package/types/config.d.ts +7 -1
  76. package/types/generated/colors.d.ts +22 -0
  77. package/types/generated/corePluginList.d.ts +1 -1
  78. package/types/generated/default-theme.d.ts +31 -2
  79. package/lib/constants.js +0 -44
  80. package/src/constants.js +0 -17
  81. /package/stubs/{defaultPostCssConfig.stub.js → postcss.config.cjs} +0 -0
@@ -931,12 +931,19 @@ function registerPlugins(plugins, context) {
931
931
  prefix(context, 'peer'),
932
932
  ]
933
933
  context.getClassOrder = function getClassOrder(classes) {
934
+ // Sort classes so they're ordered in a deterministic manner
935
+ let sorted = [...classes].sort((a, z) => {
936
+ if (a === z) return 0
937
+ if (a < z) return -1
938
+ return 1
939
+ })
940
+
934
941
  // Non-util classes won't be generated, so we default them to null
935
- let sortedClassNames = new Map(classes.map((className) => [className, null]))
942
+ let sortedClassNames = new Map(sorted.map((className) => [className, null]))
936
943
 
937
944
  // Sort all classes in order
938
945
  // Non-tailwind classes won't be generated and will be left as `null`
939
- let rules = generateRules(new Set(classes), context)
946
+ let rules = generateRules(new Set(sorted), context)
940
947
  rules = context.offsets.sort(rules)
941
948
 
942
949
  let idx = BigInt(parasiteUtilities.length)
@@ -4,13 +4,14 @@ import fs from 'fs'
4
4
  import LRU from 'quick-lru'
5
5
 
6
6
  import hash from '../util/hashConfig'
7
- import getModuleDependencies from '../lib/getModuleDependencies'
8
7
  import resolveConfig from '../public/resolve-config'
9
8
  import resolveConfigPath from '../util/resolveConfigPath'
10
9
  import { getContext, getFileModifiedMap } from './setupContextUtils'
11
10
  import parseDependency from '../util/parseDependency'
12
11
  import { validateConfig } from '../util/validateConfig.js'
13
12
  import { parseCandidateFiles, resolvedChangedContent } from './content.js'
13
+ import { loadConfig } from '../lib/load-config'
14
+ import getModuleDependencies from './getModuleDependencies'
14
15
 
15
16
  let configPathCache = new LRU({ maxSize: 100 })
16
17
 
@@ -34,7 +35,7 @@ function getTailwindConfig(configOrPath) {
34
35
  let [prevConfig, prevConfigHash, prevDeps, prevModified] =
35
36
  configPathCache.get(userConfigPath) || []
36
37
 
37
- let newDeps = getModuleDependencies(userConfigPath).map((dep) => dep.file)
38
+ let newDeps = getModuleDependencies(userConfigPath)
38
39
 
39
40
  let modified = false
40
41
  let newModified = new Map()
@@ -55,8 +56,7 @@ function getTailwindConfig(configOrPath) {
55
56
  for (let file of newDeps) {
56
57
  delete require.cache[file]
57
58
  }
58
- let newConfig = resolveConfig(require(userConfigPath))
59
- newConfig = validateConfig(newConfig)
59
+ let newConfig = validateConfig(resolveConfig(loadConfig(userConfigPath)))
60
60
  let newHash = hash(newConfig)
61
61
  configPathCache.set(userConfigPath, [newConfig, newHash, newDeps, newModified])
62
62
  return [newConfig, userConfigPath, newHash, newDeps]
@@ -1,8 +1,9 @@
1
1
  import fs from 'fs'
2
2
  import path from 'path'
3
+ import { resolveDefaultConfigPath } from '../../../util/resolveConfigPath'
3
4
  import { createProcessor } from './plugin'
4
5
 
5
- export async function build(args, configs) {
6
+ export async function build(args) {
6
7
  let input = args['--input']
7
8
  let shouldWatch = args['--watch']
8
9
 
@@ -23,11 +24,7 @@ export async function build(args, configs) {
23
24
  }
24
25
 
25
26
  // 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
- )
27
+ let configPath = args['--config'] ? args['--config'] : resolveDefaultConfigPath()
31
28
 
32
29
  let processor = await createProcessor(args, configPath)
33
30
 
@@ -42,6 +39,9 @@ export async function build(args, configs) {
42
39
 
43
40
  await processor.watch()
44
41
  } else {
45
- await processor.build()
42
+ await processor.build().catch((e) => {
43
+ console.error(e)
44
+ process.exit(1)
45
+ })
46
46
  }
47
47
  }
@@ -10,12 +10,14 @@ import { loadPostcss, loadPostcssImport, lightningcss } from './deps'
10
10
  import { formatNodes, drainStdin, outputFile } from './utils'
11
11
  import { env } from '../../../lib/sharedState'
12
12
  import resolveConfig from '../../../../resolveConfig'
13
- import getModuleDependencies from '../../../lib/getModuleDependencies'
14
13
  import { parseCandidateFiles } from '../../../lib/content'
15
14
  import { createWatcher } from './watching'
16
15
  import fastGlob from 'fast-glob'
17
16
  import { findAtConfigPath } from '../../../lib/findAtConfigPath'
18
17
  import log from '../../../util/log'
18
+ import { loadConfig } from '../../../lib/load-config'
19
+ import getModuleDependencies from '../../../lib/getModuleDependencies'
20
+ import type { Config } from '../../../../types'
19
21
 
20
22
  /**
21
23
  *
@@ -115,7 +117,9 @@ let state = {
115
117
  /** @type {{content: string, extension: string}[]} */
116
118
  changedContent: [],
117
119
 
118
- configDependencies: new Set(),
120
+ /** @type {{config: Config, dependencies: Set<string>, dispose: Function } | null} */
121
+ configBag: null,
122
+
119
123
  contextDependencies: new Set(),
120
124
 
121
125
  /** @type {import('../../lib/content.js').ContentPath[]} */
@@ -140,37 +144,35 @@ let state = {
140
144
 
141
145
  loadConfig(configPath, content) {
142
146
  if (this.watcher && configPath) {
143
- this.refreshConfigDependencies(configPath)
147
+ this.refreshConfigDependencies()
144
148
  }
145
149
 
146
- let config = configPath ? require(configPath) : {}
150
+ let config = loadConfig(configPath)
151
+ let dependencies = getModuleDependencies(configPath)
152
+ this.configBag = {
153
+ config,
154
+ dependencies,
155
+ dispose() {
156
+ for (let file of dependencies) {
157
+ delete require.cache[require.resolve(file)]
158
+ }
159
+ },
160
+ }
147
161
 
148
162
  // @ts-ignore
149
- config = resolveConfig(config, { content: { files: [] } })
163
+ this.configBag.config = resolveConfig(this.configBag.config, { content: { files: [] } })
150
164
 
151
165
  // Override content files if `--content` has been passed explicitly
152
166
  if (content?.length > 0) {
153
- config.content.files = content
167
+ this.configBag.config.content.files = content
154
168
  }
155
169
 
156
- return config
170
+ return this.configBag.config
157
171
  },
158
172
 
159
173
  refreshConfigDependencies(configPath) {
160
174
  env.DEBUG && console.time('Module dependencies')
161
-
162
- for (let file of this.configDependencies) {
163
- delete require.cache[require.resolve(file)]
164
- }
165
-
166
- if (configPath) {
167
- let deps = getModuleDependencies(configPath).map(({ file }) => file)
168
-
169
- for (let dependency of deps) {
170
- this.configDependencies.add(dependency)
171
- }
172
- }
173
-
175
+ this.configBag?.dispose()
174
176
  env.DEBUG && console.timeEnd('Module dependencies')
175
177
  },
176
178
 
@@ -380,7 +382,11 @@ export async function createProcessor(args, cliConfigPath) {
380
382
  // The watcher will start watching the imported CSS files and will be
381
383
  // resilient to future errors.
382
384
 
383
- console.error(err)
385
+ if (state.watcher) {
386
+ console.error(err)
387
+ } else {
388
+ return Promise.reject(err)
389
+ }
384
390
  }
385
391
  )
386
392
  }
@@ -413,7 +419,7 @@ export async function createProcessor(args, cliConfigPath) {
413
419
  async rebuild(changes) {
414
420
  let needsNewContext = changes.some((change) => {
415
421
  return (
416
- state.configDependencies.has(change.file) ||
422
+ state.configBag?.dependencies.has(change.file) ||
417
423
  state.contextDependencies.has(change.file)
418
424
  )
419
425
  })
@@ -218,7 +218,7 @@ export function createWatcher(args, { state, rebuild }) {
218
218
 
219
219
  refreshWatchedFiles() {
220
220
  watcher.add(Array.from(state.contextDependencies))
221
- watcher.add(Array.from(state.configDependencies))
221
+ watcher.add(Array.from(state.configBag.dependencies))
222
222
  watcher.add(state.contentPatterns.all)
223
223
  },
224
224
  }
@@ -8,19 +8,6 @@ import { build } from './build'
8
8
  import { help } from './help'
9
9
  import { init } from './init'
10
10
 
11
- function isESM() {
12
- const pkgPath = path.resolve('./package.json')
13
-
14
- try {
15
- let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
16
- return pkg.type && pkg.type === 'module'
17
- } catch (err) {
18
- return false
19
- }
20
- }
21
-
22
- let configs = isESM() ? { tailwind: 'tailwind.config.cjs' } : { tailwind: 'tailwind.config.js' }
23
-
24
11
  // ---
25
12
 
26
13
  function oneOf(...options) {
@@ -43,7 +30,12 @@ let commands = {
43
30
  init: {
44
31
  run: init,
45
32
  args: {
46
- '--full': { type: Boolean, description: `Initialize a full \`${configs.tailwind}\` file` },
33
+ '--esm': { type: Boolean, description: `Initialize configuration file as ESM` },
34
+ '--ts': { type: Boolean, description: `Initialize configuration file as TypeScript` },
35
+ '--full': {
36
+ type: Boolean,
37
+ description: `Include the default values for all options in the generated configuration file`,
38
+ },
47
39
  '-f': '--full',
48
40
  },
49
41
  },
@@ -209,4 +201,4 @@ if (args['--help']) {
209
201
  process.exit(0)
210
202
  }
211
203
 
212
- run(args, configs)
204
+ run(args)
@@ -1,22 +1,49 @@
1
1
  import fs from 'fs'
2
2
  import path from 'path'
3
3
 
4
- export function init(args, configs) {
5
- let messages = []
4
+ function isESM() {
5
+ const pkgPath = path.resolve('./package.json')
6
+
7
+ try {
8
+ let pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
9
+ return pkg.type && pkg.type === 'module'
10
+ } catch (err) {
11
+ return false
12
+ }
13
+ }
14
+
15
+ export function init(args) {
16
+ let messages: string[] = []
17
+
18
+ let isProjectESM = args['--ts'] || args['--esm'] || isESM()
19
+ let syntax = args['--ts'] ? 'ts' : isProjectESM ? 'js' : 'cjs'
20
+ let extension = args['--ts'] ? 'ts' : 'js'
21
+
22
+ let tailwindConfigLocation = path.resolve(args['_'][1] ?? `./tailwind.config.${extension}`)
6
23
 
7
- let tailwindConfigLocation = path.resolve(args['_'][1] ?? `./${configs.tailwind}`)
8
24
  if (fs.existsSync(tailwindConfigLocation)) {
9
25
  messages.push(`${path.basename(tailwindConfigLocation)} already exists.`)
10
26
  } else {
11
- let stubFile = fs.readFileSync(
27
+ let stubContentsFile = fs.readFileSync(
12
28
  args['--full']
13
- ? path.resolve(__dirname, '../../../../stubs/defaultConfig.stub.js')
14
- : path.resolve(__dirname, '../../../../stubs/simpleConfig.stub.js'),
29
+ ? path.resolve(__dirname, '../../../../stubs/config.full.js')
30
+ : path.resolve(__dirname, '../../../../stubs/config.simple.js'),
31
+ 'utf8'
32
+ )
33
+
34
+ let stubFile = fs.readFileSync(
35
+ path.resolve(__dirname, `../../../../stubs/tailwind.config.${syntax}`),
15
36
  'utf8'
16
37
  )
17
38
 
18
39
  // Change colors import
19
- stubFile = stubFile.replace('../colors', 'tailwindcss/colors')
40
+ stubContentsFile = stubContentsFile.replace('../colors', 'tailwindcss/colors')
41
+
42
+ // Replace contents of {ts,js,cjs} file with the stub {simple,full}.
43
+ stubFile =
44
+ stubFile
45
+ .replace('__CONFIG__', stubContentsFile.replace('module.exports =', '').trim())
46
+ .trim() + '\n\n'
20
47
 
21
48
  fs.writeFileSync(tailwindConfigLocation, stubFile, 'utf8')
22
49
 
@@ -24,6 +24,7 @@ export default {
24
24
  700: '#334155',
25
25
  800: '#1e293b',
26
26
  900: '#0f172a',
27
+ 950: '#020617',
27
28
  },
28
29
  gray: {
29
30
  50: '#f9fafb',
@@ -36,6 +37,7 @@ export default {
36
37
  700: '#374151',
37
38
  800: '#1f2937',
38
39
  900: '#111827',
40
+ 950: '#030712',
39
41
  },
40
42
  zinc: {
41
43
  50: '#fafafa',
@@ -48,6 +50,7 @@ export default {
48
50
  700: '#3f3f46',
49
51
  800: '#27272a',
50
52
  900: '#18181b',
53
+ 950: '#09090b',
51
54
  },
52
55
  neutral: {
53
56
  50: '#fafafa',
@@ -60,6 +63,7 @@ export default {
60
63
  700: '#404040',
61
64
  800: '#262626',
62
65
  900: '#171717',
66
+ 950: '#0a0a0a',
63
67
  },
64
68
  stone: {
65
69
  50: '#fafaf9',
@@ -72,6 +76,7 @@ export default {
72
76
  700: '#44403c',
73
77
  800: '#292524',
74
78
  900: '#1c1917',
79
+ 950: '#0c0a09',
75
80
  },
76
81
  red: {
77
82
  50: '#fef2f2',
@@ -84,6 +89,7 @@ export default {
84
89
  700: '#b91c1c',
85
90
  800: '#991b1b',
86
91
  900: '#7f1d1d',
92
+ 950: '#450a0a',
87
93
  },
88
94
  orange: {
89
95
  50: '#fff7ed',
@@ -96,6 +102,7 @@ export default {
96
102
  700: '#c2410c',
97
103
  800: '#9a3412',
98
104
  900: '#7c2d12',
105
+ 950: '#431407',
99
106
  },
100
107
  amber: {
101
108
  50: '#fffbeb',
@@ -108,6 +115,7 @@ export default {
108
115
  700: '#b45309',
109
116
  800: '#92400e',
110
117
  900: '#78350f',
118
+ 950: '#451a03',
111
119
  },
112
120
  yellow: {
113
121
  50: '#fefce8',
@@ -120,6 +128,7 @@ export default {
120
128
  700: '#a16207',
121
129
  800: '#854d0e',
122
130
  900: '#713f12',
131
+ 950: '#422006',
123
132
  },
124
133
  lime: {
125
134
  50: '#f7fee7',
@@ -132,6 +141,7 @@ export default {
132
141
  700: '#4d7c0f',
133
142
  800: '#3f6212',
134
143
  900: '#365314',
144
+ 950: '#1a2e05',
135
145
  },
136
146
  green: {
137
147
  50: '#f0fdf4',
@@ -144,6 +154,7 @@ export default {
144
154
  700: '#15803d',
145
155
  800: '#166534',
146
156
  900: '#14532d',
157
+ 950: '#052e16',
147
158
  },
148
159
  emerald: {
149
160
  50: '#ecfdf5',
@@ -156,6 +167,7 @@ export default {
156
167
  700: '#047857',
157
168
  800: '#065f46',
158
169
  900: '#064e3b',
170
+ 950: '#022c22',
159
171
  },
160
172
  teal: {
161
173
  50: '#f0fdfa',
@@ -168,6 +180,7 @@ export default {
168
180
  700: '#0f766e',
169
181
  800: '#115e59',
170
182
  900: '#134e4a',
183
+ 950: '#042f2e',
171
184
  },
172
185
  cyan: {
173
186
  50: '#ecfeff',
@@ -180,6 +193,7 @@ export default {
180
193
  700: '#0e7490',
181
194
  800: '#155e75',
182
195
  900: '#164e63',
196
+ 950: '#083344',
183
197
  },
184
198
  sky: {
185
199
  50: '#f0f9ff',
@@ -192,6 +206,7 @@ export default {
192
206
  700: '#0369a1',
193
207
  800: '#075985',
194
208
  900: '#0c4a6e',
209
+ 950: '#082f49',
195
210
  },
196
211
  blue: {
197
212
  50: '#eff6ff',
@@ -204,6 +219,7 @@ export default {
204
219
  700: '#1d4ed8',
205
220
  800: '#1e40af',
206
221
  900: '#1e3a8a',
222
+ 950: '#172554',
207
223
  },
208
224
  indigo: {
209
225
  50: '#eef2ff',
@@ -216,6 +232,7 @@ export default {
216
232
  700: '#4338ca',
217
233
  800: '#3730a3',
218
234
  900: '#312e81',
235
+ 950: '#1e1b4b',
219
236
  },
220
237
  violet: {
221
238
  50: '#f5f3ff',
@@ -228,6 +245,7 @@ export default {
228
245
  700: '#6d28d9',
229
246
  800: '#5b21b6',
230
247
  900: '#4c1d95',
248
+ 950: '#2e1065',
231
249
  },
232
250
  purple: {
233
251
  50: '#faf5ff',
@@ -240,6 +258,7 @@ export default {
240
258
  700: '#7e22ce',
241
259
  800: '#6b21a8',
242
260
  900: '#581c87',
261
+ 950: '#3b0764',
243
262
  },
244
263
  fuchsia: {
245
264
  50: '#fdf4ff',
@@ -252,6 +271,7 @@ export default {
252
271
  700: '#a21caf',
253
272
  800: '#86198f',
254
273
  900: '#701a75',
274
+ 950: '#4a044e',
255
275
  },
256
276
  pink: {
257
277
  50: '#fdf2f8',
@@ -264,6 +284,7 @@ export default {
264
284
  700: '#be185d',
265
285
  800: '#9d174d',
266
286
  900: '#831843',
287
+ 950: '#500724',
267
288
  },
268
289
  rose: {
269
290
  50: '#fff1f2',
@@ -276,6 +297,7 @@ export default {
276
297
  700: '#be123c',
277
298
  800: '#9f1239',
278
299
  900: '#881337',
300
+ 950: '#4c0519',
279
301
  },
280
302
  get lightBlue() {
281
303
  warn({ version: 'v2.2', from: 'lightBlue', to: 'sky' })
@@ -1,4 +1,4 @@
1
1
  import { cloneDeep } from '../util/cloneDeep'
2
- import defaultConfig from '../../stubs/defaultConfig.stub'
2
+ import defaultConfig from '../../stubs/config.full'
3
3
 
4
4
  export default cloneDeep(defaultConfig)
@@ -1,4 +1,4 @@
1
1
  import { cloneDeep } from '../util/cloneDeep'
2
- import defaultConfig from '../../stubs/defaultConfig.stub'
2
+ import defaultFullConfig from '../../stubs/config.full'
3
3
 
4
- export default cloneDeep(defaultConfig.theme)
4
+ export default cloneDeep(defaultFullConfig.theme)
@@ -0,0 +1,2 @@
1
+ import { loadConfig } from '../lib/load-config'
2
+ export default loadConfig
@@ -0,0 +1,19 @@
1
+ import { splitAtTopLevelOnly } from './splitAtTopLevelOnly'
2
+
3
+ export function applyImportantSelector(selector, important) {
4
+ let matches = /^(.*?)(:before|:after|::[\w-]+)(\)*)$/g.exec(selector)
5
+ if (!matches) return `${important} ${wrapWithIs(selector)}`
6
+
7
+ let [, before, pseudo, brackets] = matches
8
+ return `${important} ${wrapWithIs(before + brackets)}${pseudo}`
9
+ }
10
+
11
+ function wrapWithIs(selector) {
12
+ let parts = splitAtTopLevelOnly(selector, ' ')
13
+
14
+ if (parts.length === 1 && parts[0].startsWith(':is(') && parts[0].endsWith(')')) {
15
+ return selector
16
+ }
17
+
18
+ return `:is(${selector})`
19
+ }
@@ -16,6 +16,10 @@ const placeholderRe = new RegExp(placeholder, 'g')
16
16
  // This is not a data type, but rather a function that can normalize the
17
17
  // correct values.
18
18
  export function normalize(value, isRoot = true) {
19
+ if (value.startsWith('--')) {
20
+ return `var(${value})`
21
+ }
22
+
19
23
  // Keep raw strings if it starts with `url(`
20
24
  if (value.includes('url(')) {
21
25
  return value
@@ -1,8 +1,8 @@
1
- import defaultConfig from '../../stubs/defaultConfig.stub.js'
1
+ import defaultFullConfig from '../../stubs/config.full.js'
2
2
  import { flagEnabled } from '../featureFlags'
3
3
 
4
4
  export default function getAllConfigs(config) {
5
- const configs = (config?.presets ?? [defaultConfig])
5
+ const configs = (config?.presets ?? [defaultFullConfig])
6
6
  .slice()
7
7
  .reverse()
8
8
  .flatMap((preset) => getAllConfigs(preset instanceof Function ? preset() : preset))
@@ -1,3 +1,4 @@
1
+ import { flagEnabled } from '../featureFlags'
1
2
  import log, { dim } from './log'
2
3
 
3
4
  export function normalizeConfig(config) {
@@ -189,7 +190,7 @@ export function normalizeConfig(config) {
189
190
  return content.relative
190
191
  }
191
192
 
192
- return config.future?.relativeContentPathsByDefault ?? false
193
+ return flagEnabled(config, 'relativeContentPathsByDefault')
193
194
  })(),
194
195
 
195
196
  files: (() => {
@@ -296,5 +297,22 @@ export function normalizeConfig(config) {
296
297
  }
297
298
  }
298
299
 
300
+ // Warn if the line-clamp plugin is installed
301
+ if (config.plugins.length > 0) {
302
+ let plugin
303
+ try {
304
+ plugin = require('@tailwindcss/line-clamp')
305
+ } catch {}
306
+
307
+ if (plugin && config.plugins.includes(plugin)) {
308
+ log.warn('line-clamp-in-core', [
309
+ 'As of Tailwind CSS v3.3, the `@tailwindcss/line-clamp` plugin is now included by default.',
310
+ 'Remove it from the `plugins` array in your configuration to eliminate this warning.',
311
+ ])
312
+
313
+ config.plugins = config.plugins.filter((p) => p !== plugin)
314
+ }
315
+ }
316
+
299
317
  return config
300
318
  }
@@ -114,6 +114,14 @@ export function parseColorFormat(value) {
114
114
  return value
115
115
  }
116
116
 
117
+ function unwrapArbitraryModifier(modifier) {
118
+ modifier = modifier.slice(1, -1)
119
+ if (modifier.startsWith('--')) {
120
+ modifier = `var(${modifier})`
121
+ }
122
+ return modifier
123
+ }
124
+
117
125
  export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
118
126
  if (options.values?.[modifier] !== undefined) {
119
127
  return parseColorFormat(options.values?.[modifier])
@@ -134,7 +142,7 @@ export function asColor(modifier, options = {}, { tailwindConfig = {} } = {}) {
134
142
  normalizedColor = parseColorFormat(normalizedColor)
135
143
 
136
144
  if (isArbitraryValue(alpha)) {
137
- return withAlphaValue(normalizedColor, alpha.slice(1, -1))
145
+ return withAlphaValue(normalizedColor, unwrapArbitraryModifier(alpha))
138
146
  }
139
147
 
140
148
  if (tailwindConfig.theme?.opacity?.[alpha] === undefined) {
@@ -268,7 +276,7 @@ export function* getMatchingTypes(types, rawModifier, options, tailwindConfig) {
268
276
  if (configValue !== null) {
269
277
  utilityModifier = configValue
270
278
  } else if (isArbitraryValue(utilityModifier)) {
271
- utilityModifier = utilityModifier.slice(1, -1)
279
+ utilityModifier = unwrapArbitraryModifier(utilityModifier)
272
280
  }
273
281
  }
274
282
  }
@@ -1,6 +1,13 @@
1
1
  import fs from 'fs'
2
2
  import path from 'path'
3
3
 
4
+ const defaultConfigFiles = [
5
+ './tailwind.config.js',
6
+ './tailwind.config.cjs',
7
+ './tailwind.config.mjs',
8
+ './tailwind.config.ts',
9
+ ]
10
+
4
11
  function isObject(value) {
5
12
  return typeof value === 'object' && value !== null
6
13
  }
@@ -43,7 +50,11 @@ export default function resolveConfigPath(pathOrConfig) {
43
50
  }
44
51
 
45
52
  // require('tailwindcss')
46
- for (const configFile of ['./tailwind.config.js', './tailwind.config.cjs']) {
53
+ return resolveDefaultConfigPath()
54
+ }
55
+
56
+ export function resolveDefaultConfigPath() {
57
+ for (const configFile of defaultConfigFiles) {
47
58
  try {
48
59
  const configPath = path.resolve(configFile)
49
60
  fs.accessSync(configPath)
@@ -17,17 +17,24 @@ export function splitAtTopLevelOnly(input, separator) {
17
17
  let stack = []
18
18
  let parts = []
19
19
  let lastPos = 0
20
+ let isEscaped = false
20
21
 
21
22
  for (let idx = 0; idx < input.length; idx++) {
22
23
  let char = input[idx]
23
24
 
24
- if (stack.length === 0 && char === separator[0]) {
25
+ if (stack.length === 0 && char === separator[0] && !isEscaped) {
25
26
  if (separator.length === 1 || input.slice(idx, idx + separator.length) === separator) {
26
27
  parts.push(input.slice(lastPos, idx))
27
28
  lastPos = idx + separator.length
28
29
  }
29
30
  }
30
31
 
32
+ if (isEscaped) {
33
+ isEscaped = false
34
+ } else if (char === '\\') {
35
+ isEscaped = true
36
+ }
37
+
31
38
  if (char === '(' || char === '[' || char === '{') {
32
39
  stack.push(char)
33
40
  } else if (
@@ -0,0 +1 @@
1
+ !*
@@ -0,0 +1,6 @@
1
+ {
2
+ "printWidth": 120,
3
+ "semi": false,
4
+ "singleQuote": true,
5
+ "trailingComma": "es5"
6
+ }