tailwindcss 3.0.23 → 3.0.24
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.
- package/CHANGELOG.md +29 -3
- package/lib/cli-peer-dependencies.js +3 -3
- package/lib/cli.js +183 -161
- package/lib/constants.js +8 -8
- package/lib/corePlugins.js +1572 -1523
- package/lib/featureFlags.js +9 -9
- package/lib/index.js +19 -6
- package/lib/lib/cacheInvalidation.js +69 -0
- package/lib/lib/collapseAdjacentRules.js +26 -13
- package/lib/lib/collapseDuplicateDeclarations.js +1 -1
- package/lib/lib/defaultExtractor.js +6 -6
- package/lib/lib/detectNesting.js +9 -9
- package/lib/lib/evaluateTailwindFunctions.js +16 -16
- package/lib/lib/expandApplyAtRules.js +180 -27
- package/lib/lib/expandTailwindAtRules.js +132 -122
- package/lib/lib/generateRules.js +90 -72
- package/lib/lib/getModuleDependencies.js +14 -14
- package/lib/lib/normalizeTailwindDirectives.js +35 -35
- package/lib/lib/partitionApplyAtRules.js +7 -7
- package/lib/lib/resolveDefaultsAtRules.js +81 -77
- package/lib/lib/setupContextUtils.js +78 -87
- package/lib/lib/setupTrackingContext.js +57 -57
- package/lib/lib/sharedState.js +10 -8
- package/lib/lib/substituteScreenAtRules.js +2 -2
- package/lib/postcss-plugins/nesting/README.md +2 -2
- package/lib/postcss-plugins/nesting/index.js +1 -1
- package/lib/postcss-plugins/nesting/plugin.js +41 -9
- package/lib/processTailwindFeatures.js +7 -7
- package/lib/public/colors.js +241 -241
- package/lib/public/resolve-config.js +5 -5
- package/lib/util/buildMediaQuery.js +2 -2
- package/lib/util/cloneDeep.js +1 -1
- package/lib/util/cloneNodes.js +12 -1
- package/lib/util/color.js +21 -20
- package/lib/util/createUtilityPlugin.js +6 -6
- package/lib/util/dataTypes.js +77 -75
- package/lib/util/escapeClassName.js +5 -5
- package/lib/util/escapeCommas.js +1 -1
- package/lib/util/flattenColorPalette.js +2 -2
- package/lib/util/formatVariantSelector.js +19 -19
- package/lib/util/getAllConfigs.js +5 -5
- package/lib/util/hashConfig.js +5 -5
- package/lib/util/isKeyframeRule.js +1 -1
- package/lib/util/isPlainObject.js +1 -1
- package/lib/util/isValidArbitraryValue.js +27 -27
- package/lib/util/log.js +8 -8
- package/lib/util/nameClass.js +7 -7
- package/lib/util/negateValue.js +4 -4
- package/lib/util/normalizeConfig.js +39 -39
- package/lib/util/normalizeScreens.js +4 -4
- package/lib/util/parseAnimationValue.js +56 -56
- package/lib/util/parseBoxShadowValue.js +60 -20
- package/lib/util/parseDependency.js +32 -32
- package/lib/util/parseObjectStyles.js +6 -6
- package/lib/util/pluginUtils.js +9 -9
- package/lib/util/prefixSelector.js +1 -1
- package/lib/util/resolveConfig.js +28 -28
- package/lib/util/resolveConfigPath.js +16 -16
- package/lib/util/responsive.js +6 -6
- package/lib/util/toColorValue.js +1 -1
- package/lib/util/toPath.js +2 -2
- package/lib/util/transformThemeValue.js +27 -27
- package/lib/util/withAlphaVariable.js +19 -19
- package/package.json +24 -23
- package/peers/index.js +4777 -4831
- package/scripts/generate-types.js +52 -0
- package/src/cli.js +41 -11
- package/src/corePlugins.js +67 -5
- package/src/featureFlags.js +2 -2
- package/src/index.js +17 -1
- package/src/lib/cacheInvalidation.js +52 -0
- package/src/lib/collapseAdjacentRules.js +16 -1
- package/src/lib/defaultExtractor.js +4 -4
- package/src/lib/expandApplyAtRules.js +179 -6
- package/src/lib/expandTailwindAtRules.js +25 -5
- package/src/lib/generateRules.js +68 -46
- package/src/lib/resolveDefaultsAtRules.js +6 -2
- package/src/lib/setupContextUtils.js +25 -26
- package/src/lib/setupTrackingContext.js +3 -3
- package/src/lib/sharedState.js +1 -0
- package/src/postcss-plugins/nesting/README.md +2 -2
- package/src/postcss-plugins/nesting/plugin.js +36 -0
- package/src/util/cloneNodes.js +14 -1
- package/src/util/color.js +7 -5
- package/src/util/dataTypes.js +3 -1
- package/src/util/log.js +7 -7
- package/src/util/parseBoxShadowValue.js +50 -2
- package/src/util/resolveConfig.js +32 -0
- package/stubs/defaultConfig.stub.js +5 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import prettier from 'prettier'
|
|
2
|
+
import { corePlugins } from '../src/corePlugins'
|
|
3
|
+
import colors from '../src/public/colors'
|
|
4
|
+
import fs from 'fs'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
|
|
7
|
+
fs.writeFileSync(
|
|
8
|
+
path.join(process.cwd(), 'types', 'generated', 'corePluginList.d.ts'),
|
|
9
|
+
`export type CorePluginList = ${Object.keys(corePlugins)
|
|
10
|
+
.map((p) => `'${p}'`)
|
|
11
|
+
.join(' | ')}`
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
let colorsWithoutDeprecatedColors = Object.fromEntries(
|
|
15
|
+
Object.entries(Object.getOwnPropertyDescriptors(colors))
|
|
16
|
+
.filter(([_, { value }]) => {
|
|
17
|
+
return typeof value !== 'undefined'
|
|
18
|
+
})
|
|
19
|
+
.map(([name, definition]) => [name, definition.value])
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
let deprecatedColors = Object.entries(Object.getOwnPropertyDescriptors(colors))
|
|
23
|
+
.filter(([_, { value }]) => {
|
|
24
|
+
return typeof value === 'undefined'
|
|
25
|
+
})
|
|
26
|
+
.map(([name, definition]) => {
|
|
27
|
+
let warn = console.warn
|
|
28
|
+
let messages = []
|
|
29
|
+
console.warn = (...args) => messages.push(args.pop())
|
|
30
|
+
definition.get()
|
|
31
|
+
console.warn = warn
|
|
32
|
+
let message = messages.join(' ').trim()
|
|
33
|
+
let newColor = message.match(/renamed to `(.*)`/)[1]
|
|
34
|
+
return `/** @deprecated ${message} */${name}: DefaultColors['${newColor}'],`
|
|
35
|
+
})
|
|
36
|
+
.join('\n')
|
|
37
|
+
|
|
38
|
+
fs.writeFileSync(
|
|
39
|
+
path.join(process.cwd(), 'types', 'generated', 'colors.d.ts'),
|
|
40
|
+
prettier.format(
|
|
41
|
+
`export interface DefaultColors { ${JSON.stringify(colorsWithoutDeprecatedColors).slice(
|
|
42
|
+
1,
|
|
43
|
+
-1
|
|
44
|
+
)}\n${deprecatedColors}\n}`,
|
|
45
|
+
{
|
|
46
|
+
semi: false,
|
|
47
|
+
singleQuote: true,
|
|
48
|
+
printWidth: 100,
|
|
49
|
+
parser: 'typescript',
|
|
50
|
+
}
|
|
51
|
+
)
|
|
52
|
+
)
|
package/src/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import path from 'path'
|
|
|
7
7
|
import arg from 'arg'
|
|
8
8
|
import fs from 'fs'
|
|
9
9
|
import postcssrc from 'postcss-load-config'
|
|
10
|
-
import {
|
|
10
|
+
import { lilconfig } from 'lilconfig'
|
|
11
11
|
import loadPlugins from 'postcss-load-config/src/plugins' // Little bit scary, looking at private/internal API
|
|
12
12
|
import tailwind from './processTailwindFeatures'
|
|
13
13
|
import resolveConfigInternal from '../resolveConfig'
|
|
@@ -151,6 +151,10 @@ let commands = {
|
|
|
151
151
|
args: {
|
|
152
152
|
'--full': { type: Boolean, description: 'Initialize a full `tailwind.config.js` file' },
|
|
153
153
|
'--postcss': { type: Boolean, description: 'Initialize a `postcss.config.js` file' },
|
|
154
|
+
'--types': {
|
|
155
|
+
type: Boolean,
|
|
156
|
+
description: 'Add TypeScript types for the `tailwind.config.js` file',
|
|
157
|
+
},
|
|
154
158
|
'-f': '--full',
|
|
155
159
|
'-p': '--postcss',
|
|
156
160
|
},
|
|
@@ -161,6 +165,12 @@ let commands = {
|
|
|
161
165
|
'--input': { type: String, description: 'Input file' },
|
|
162
166
|
'--output': { type: String, description: 'Output file' },
|
|
163
167
|
'--watch': { type: Boolean, description: 'Watch for changes and rebuild as needed' },
|
|
168
|
+
/*
|
|
169
|
+
'--poll': {
|
|
170
|
+
type: Boolean,
|
|
171
|
+
description: 'Use polling instead of filesystem events when watching',
|
|
172
|
+
},
|
|
173
|
+
*/
|
|
164
174
|
'--content': {
|
|
165
175
|
type: String,
|
|
166
176
|
description: 'Content paths to use for removing unused classes',
|
|
@@ -187,6 +197,9 @@ let commands = {
|
|
|
187
197
|
'-o': '--output',
|
|
188
198
|
'-m': '--minify',
|
|
189
199
|
'-w': '--watch',
|
|
200
|
+
/*
|
|
201
|
+
'-p': '--poll',
|
|
202
|
+
*/
|
|
190
203
|
},
|
|
191
204
|
},
|
|
192
205
|
}
|
|
@@ -204,7 +217,7 @@ if (
|
|
|
204
217
|
help({
|
|
205
218
|
usage: [
|
|
206
219
|
'tailwindcss [--input input.css] [--output output.css] [--watch] [options...]',
|
|
207
|
-
'tailwindcss init [--full] [--postcss] [options...]',
|
|
220
|
+
'tailwindcss init [--full] [--postcss] [--types] [options...]',
|
|
208
221
|
],
|
|
209
222
|
commands: Object.keys(commands)
|
|
210
223
|
.filter((command) => command !== 'build')
|
|
@@ -331,6 +344,13 @@ function init() {
|
|
|
331
344
|
'utf8'
|
|
332
345
|
)
|
|
333
346
|
|
|
347
|
+
if (args['--types']) {
|
|
348
|
+
let typesHeading = "/** @type {import('tailwindcss/types').Config} */"
|
|
349
|
+
stubFile =
|
|
350
|
+
stubFile.replace(`module.exports = `, `${typesHeading}\nconst config = `) +
|
|
351
|
+
'\nmodule.exports = config'
|
|
352
|
+
}
|
|
353
|
+
|
|
334
354
|
// Change colors import
|
|
335
355
|
stubFile = stubFile.replace('../colors', 'tailwindcss/colors')
|
|
336
356
|
|
|
@@ -367,8 +387,17 @@ async function build() {
|
|
|
367
387
|
let input = args['--input']
|
|
368
388
|
let output = args['--output']
|
|
369
389
|
let shouldWatch = args['--watch']
|
|
390
|
+
let shouldPoll = false
|
|
391
|
+
/*
|
|
392
|
+
let shouldPoll = args['--poll']
|
|
393
|
+
*/
|
|
394
|
+
let shouldCoalesceWriteEvents = shouldPoll || process.platform === 'win32'
|
|
370
395
|
let includePostCss = args['--postcss']
|
|
371
396
|
|
|
397
|
+
// Polling interval in milliseconds
|
|
398
|
+
// Used only when polling or coalescing add/change events on Windows
|
|
399
|
+
let pollInterval = 10
|
|
400
|
+
|
|
372
401
|
// TODO: Deprecate this in future versions
|
|
373
402
|
if (!input && args['_'][1]) {
|
|
374
403
|
console.error('[deprecation] Running tailwindcss without -i, please provide an input file.')
|
|
@@ -397,8 +426,8 @@ async function build() {
|
|
|
397
426
|
? await (async () => {
|
|
398
427
|
let file = path.resolve(customPostCssPath)
|
|
399
428
|
|
|
400
|
-
// Implementation, see: https://unpkg.com/browse/postcss-load-config@3.0
|
|
401
|
-
let { config = {} } = await
|
|
429
|
+
// Implementation, see: https://unpkg.com/browse/postcss-load-config@3.1.0/src/index.js
|
|
430
|
+
let { config = {} } = await lilconfig('postcss').load(file)
|
|
402
431
|
if (typeof config === 'function') {
|
|
403
432
|
config = config()
|
|
404
433
|
} else {
|
|
@@ -746,14 +775,15 @@ async function build() {
|
|
|
746
775
|
}
|
|
747
776
|
|
|
748
777
|
watcher = chokidar.watch([...contextDependencies, ...extractFileGlobs(config)], {
|
|
778
|
+
usePolling: shouldPoll,
|
|
779
|
+
interval: shouldPoll ? pollInterval : undefined,
|
|
749
780
|
ignoreInitial: true,
|
|
750
|
-
awaitWriteFinish:
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
: false,
|
|
781
|
+
awaitWriteFinish: shouldCoalesceWriteEvents
|
|
782
|
+
? {
|
|
783
|
+
stabilityThreshold: 50,
|
|
784
|
+
pollInterval: pollInterval,
|
|
785
|
+
}
|
|
786
|
+
: false,
|
|
757
787
|
})
|
|
758
788
|
|
|
759
789
|
let chain = Promise.resolve()
|
package/src/corePlugins.js
CHANGED
|
@@ -3,6 +3,7 @@ import * as path from 'path'
|
|
|
3
3
|
import postcss from 'postcss'
|
|
4
4
|
import createUtilityPlugin from './util/createUtilityPlugin'
|
|
5
5
|
import buildMediaQuery from './util/buildMediaQuery'
|
|
6
|
+
import escapeClassName from './util/escapeClassName'
|
|
6
7
|
import parseAnimationValue from './util/parseAnimationValue'
|
|
7
8
|
import flattenColorPalette from './util/flattenColorPalette'
|
|
8
9
|
import withAlphaVariable, { withAlphaValue } from './util/withAlphaVariable'
|
|
@@ -26,6 +27,10 @@ export let variantPlugins = {
|
|
|
26
27
|
|
|
27
28
|
addVariant('placeholder', '&::placeholder')
|
|
28
29
|
|
|
30
|
+
/*
|
|
31
|
+
addVariant('backdrop', '&::backdrop')
|
|
32
|
+
*/
|
|
33
|
+
|
|
29
34
|
addVariant('before', ({ container }) => {
|
|
30
35
|
container.walkRules((rule) => {
|
|
31
36
|
let foundContent = false
|
|
@@ -117,6 +122,9 @@ export let variantPlugins = {
|
|
|
117
122
|
'focus',
|
|
118
123
|
'focus-visible',
|
|
119
124
|
'active',
|
|
125
|
+
/*
|
|
126
|
+
'enabled',
|
|
127
|
+
*/
|
|
120
128
|
'disabled',
|
|
121
129
|
].map((variant) => (Array.isArray(variant) ? variant : [variant, `:${variant}`]))
|
|
122
130
|
|
|
@@ -171,7 +179,8 @@ export let variantPlugins = {
|
|
|
171
179
|
},
|
|
172
180
|
|
|
173
181
|
darkVariants: ({ config, addVariant }) => {
|
|
174
|
-
let mode = config('darkMode', 'media')
|
|
182
|
+
let [mode] = [].concat(config('darkMode', 'media'))
|
|
183
|
+
|
|
175
184
|
if (mode === false) {
|
|
176
185
|
mode = 'media'
|
|
177
186
|
log.warn('darkmode-false', [
|
|
@@ -182,7 +191,10 @@ export let variantPlugins = {
|
|
|
182
191
|
}
|
|
183
192
|
|
|
184
193
|
if (mode === 'class') {
|
|
185
|
-
addVariant('dark',
|
|
194
|
+
addVariant('dark', `.dark &`)
|
|
195
|
+
/*
|
|
196
|
+
addVariant('dark', `${className} &`)
|
|
197
|
+
*/
|
|
186
198
|
} else if (mode === 'media') {
|
|
187
199
|
addVariant('dark', '@media (prefers-color-scheme: dark)')
|
|
188
200
|
}
|
|
@@ -527,6 +539,43 @@ export let corePlugins = {
|
|
|
527
539
|
})
|
|
528
540
|
},
|
|
529
541
|
|
|
542
|
+
/*
|
|
543
|
+
borderSpacing: ({ addDefaults, matchUtilities, theme }) => {
|
|
544
|
+
addDefaults('border-spacing', {
|
|
545
|
+
'--tw-border-spacing-x': 0,
|
|
546
|
+
'--tw-border-spacing-y': 0,
|
|
547
|
+
})
|
|
548
|
+
|
|
549
|
+
matchUtilities(
|
|
550
|
+
{
|
|
551
|
+
'border-spacing': (value) => {
|
|
552
|
+
return {
|
|
553
|
+
'--tw-border-spacing-x': value,
|
|
554
|
+
'--tw-border-spacing-y': value,
|
|
555
|
+
'@defaults border-spacing': {},
|
|
556
|
+
'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
|
|
557
|
+
}
|
|
558
|
+
},
|
|
559
|
+
'border-spacing-x': (value) => {
|
|
560
|
+
return {
|
|
561
|
+
'--tw-border-spacing-x': value,
|
|
562
|
+
'@defaults border-spacing': {},
|
|
563
|
+
'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
'border-spacing-y': (value) => {
|
|
567
|
+
return {
|
|
568
|
+
'--tw-border-spacing-y': value,
|
|
569
|
+
'@defaults border-spacing': {},
|
|
570
|
+
'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)',
|
|
571
|
+
}
|
|
572
|
+
},
|
|
573
|
+
},
|
|
574
|
+
{ values: theme('borderSpacing') }
|
|
575
|
+
)
|
|
576
|
+
},
|
|
577
|
+
*/
|
|
578
|
+
|
|
530
579
|
transformOrigin: createUtilityPlugin('transformOrigin', [['origin', ['transformOrigin']]]),
|
|
531
580
|
translate: createUtilityPlugin(
|
|
532
581
|
'translate',
|
|
@@ -611,8 +660,8 @@ export let corePlugins = {
|
|
|
611
660
|
})
|
|
612
661
|
},
|
|
613
662
|
|
|
614
|
-
animation: ({ matchUtilities, theme,
|
|
615
|
-
let prefixName = (name) => prefix(
|
|
663
|
+
animation: ({ matchUtilities, theme, config }) => {
|
|
664
|
+
let prefixName = (name) => `${config('prefix')}${escapeClassName(name)}`
|
|
616
665
|
let keyframes = Object.fromEntries(
|
|
617
666
|
Object.entries(theme('keyframes') ?? {}).map(([key, value]) => {
|
|
618
667
|
return [key, { [`@keyframes ${prefixName(key)}`]: value }]
|
|
@@ -1522,6 +1571,10 @@ export let corePlugins = {
|
|
|
1522
1571
|
'.text-center': { 'text-align': 'center' },
|
|
1523
1572
|
'.text-right': { 'text-align': 'right' },
|
|
1524
1573
|
'.text-justify': { 'text-align': 'justify' },
|
|
1574
|
+
/*
|
|
1575
|
+
'.text-start': { 'text-align': 'start' },
|
|
1576
|
+
'.text-end': { 'text-align': 'end' },
|
|
1577
|
+
*/
|
|
1525
1578
|
})
|
|
1526
1579
|
},
|
|
1527
1580
|
|
|
@@ -1925,6 +1978,9 @@ export let corePlugins = {
|
|
|
1925
1978
|
ringWidth: ({ matchUtilities, addDefaults, addUtilities, theme }) => {
|
|
1926
1979
|
let ringOpacityDefault = theme('ringOpacity.DEFAULT', '0.5')
|
|
1927
1980
|
let ringColorDefault = withAlphaValue(
|
|
1981
|
+
/*
|
|
1982
|
+
theme('ringColor')?.DEFAULT,
|
|
1983
|
+
*/
|
|
1928
1984
|
theme('ringColor.DEFAULT'),
|
|
1929
1985
|
ringOpacityDefault,
|
|
1930
1986
|
`rgb(147 197 253 / ${ringOpacityDefault})`
|
|
@@ -1964,10 +2020,16 @@ export let corePlugins = {
|
|
|
1964
2020
|
})
|
|
1965
2021
|
},
|
|
1966
2022
|
|
|
1967
|
-
ringColor: ({ matchUtilities, theme }) => {
|
|
2023
|
+
ringColor: ({ matchUtilities, theme, corePlugins }) => {
|
|
1968
2024
|
matchUtilities(
|
|
1969
2025
|
{
|
|
1970
2026
|
ring: (value) => {
|
|
2027
|
+
if (!corePlugins('ringOpacity')) {
|
|
2028
|
+
return {
|
|
2029
|
+
'--tw-ring-color': toColorValue(value),
|
|
2030
|
+
}
|
|
2031
|
+
}
|
|
2032
|
+
|
|
1971
2033
|
return withAlphaVariable({
|
|
1972
2034
|
color: value,
|
|
1973
2035
|
property: '--tw-ring-color',
|
package/src/featureFlags.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import colors from 'picocolors'
|
|
2
2
|
import log from './util/log'
|
|
3
3
|
|
|
4
4
|
let defaults = {
|
|
@@ -41,7 +41,7 @@ export function issueFlagNotices(config) {
|
|
|
41
41
|
|
|
42
42
|
if (experimentalFlagsEnabled(config).length > 0) {
|
|
43
43
|
let changes = experimentalFlagsEnabled(config)
|
|
44
|
-
.map((s) =>
|
|
44
|
+
.map((s) => colors.yellow(s))
|
|
45
45
|
.join(', ')
|
|
46
46
|
|
|
47
47
|
log.warn('experimental-flags-enabled', [
|
package/src/index.js
CHANGED
|
@@ -13,7 +13,23 @@ module.exports = function tailwindcss(configOrPath) {
|
|
|
13
13
|
return root
|
|
14
14
|
},
|
|
15
15
|
function (root, result) {
|
|
16
|
-
|
|
16
|
+
let context = setupTrackingContext(configOrPath)
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
if (root.type === 'document') {
|
|
20
|
+
let roots = root.nodes.filter((node) => node.type === 'root')
|
|
21
|
+
|
|
22
|
+
for (const root of roots) {
|
|
23
|
+
if (root.type === 'root') {
|
|
24
|
+
processTailwindFeatures(context)(root, result)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
processTailwindFeatures(context)(root, result)
|
|
17
33
|
},
|
|
18
34
|
env.DEBUG &&
|
|
19
35
|
function (root) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import crypto from 'crypto'
|
|
2
|
+
import * as sharedState from './sharedState'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Calculate the hash of a string.
|
|
6
|
+
*
|
|
7
|
+
* This doesn't need to be cryptographically secure or
|
|
8
|
+
* anything like that since it's used only to detect
|
|
9
|
+
* when the CSS changes to invalidate the context.
|
|
10
|
+
*
|
|
11
|
+
* This is wrapped in a try/catch because it's really dependent
|
|
12
|
+
* on how Node itself is build and the environment and OpenSSL
|
|
13
|
+
* version / build that is installed on the user's machine.
|
|
14
|
+
*
|
|
15
|
+
* Based on the environment this can just outright fail.
|
|
16
|
+
*
|
|
17
|
+
* See https://github.com/nodejs/node/issues/40455
|
|
18
|
+
*
|
|
19
|
+
* @param {string} str
|
|
20
|
+
*/
|
|
21
|
+
function getHash(str) {
|
|
22
|
+
try {
|
|
23
|
+
return crypto.createHash('md5').update(str, 'utf-8').digest('binary')
|
|
24
|
+
} catch (err) {
|
|
25
|
+
return ''
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Determine if the CSS tree is different from the
|
|
31
|
+
* previous version for the given `sourcePath`.
|
|
32
|
+
*
|
|
33
|
+
* @param {string} sourcePath
|
|
34
|
+
* @param {import('postcss').Node} root
|
|
35
|
+
*/
|
|
36
|
+
export function hasContentChanged(sourcePath, root) {
|
|
37
|
+
let css = root.toString()
|
|
38
|
+
|
|
39
|
+
// We only care about files with @tailwind directives
|
|
40
|
+
// Other files use an existing context
|
|
41
|
+
if (!css.includes('@tailwind')) {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
let existingHash = sharedState.sourceHashMap.get(sourcePath)
|
|
46
|
+
let rootHash = getHash(css)
|
|
47
|
+
let didChange = existingHash !== rootHash
|
|
48
|
+
|
|
49
|
+
sharedState.sourceHashMap.set(sourcePath, rootHash)
|
|
50
|
+
|
|
51
|
+
return didChange
|
|
52
|
+
}
|
|
@@ -5,7 +5,7 @@ let comparisonMap = {
|
|
|
5
5
|
let types = new Set(Object.keys(comparisonMap))
|
|
6
6
|
|
|
7
7
|
export default function collapseAdjacentRules() {
|
|
8
|
-
|
|
8
|
+
function collapseRulesIn(root) {
|
|
9
9
|
let currentRule = null
|
|
10
10
|
root.each((node) => {
|
|
11
11
|
if (!types.has(node.type)) {
|
|
@@ -35,5 +35,20 @@ export default function collapseAdjacentRules() {
|
|
|
35
35
|
currentRule = node
|
|
36
36
|
}
|
|
37
37
|
})
|
|
38
|
+
|
|
39
|
+
// After we've collapsed adjacent rules & at-rules, we need to collapse
|
|
40
|
+
// adjacent rules & at-rules that are children of at-rules.
|
|
41
|
+
// We do not care about nesting rules because Tailwind CSS
|
|
42
|
+
// explicitly does not handle rule nesting on its own as
|
|
43
|
+
// the user is expected to use a nesting plugin
|
|
44
|
+
root.each((node) => {
|
|
45
|
+
if (node.type === 'atrule') {
|
|
46
|
+
collapseRulesIn(node)
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return (root) => {
|
|
52
|
+
collapseRulesIn(root)
|
|
38
53
|
}
|
|
39
54
|
}
|
|
@@ -2,16 +2,16 @@ const PATTERNS = [
|
|
|
2
2
|
/(?:\['([^'\s]+[^<>"'`\s:\\])')/.source, // ['text-lg' -> text-lg
|
|
3
3
|
/(?:\["([^"\s]+[^<>"'`\s:\\])")/.source, // ["text-lg" -> text-lg
|
|
4
4
|
/(?:\[`([^`\s]+[^<>"'`\s:\\])`)/.source, // [`text-lg` -> text-lg
|
|
5
|
-
/([
|
|
6
|
-
/([
|
|
5
|
+
/([^${(<>"'`\s]*\[\w*'[^"`\s]*'?\])/.source, // font-['some_font',sans-serif]
|
|
6
|
+
/([^${(<>"'`\s]*\[\w*"[^'`\s]*"?\])/.source, // font-["some_font",sans-serif]
|
|
7
7
|
/([^<>"'`\s]*\[\w*\('[^"'`\s]*'\)\])/.source, // bg-[url('...')]
|
|
8
8
|
/([^<>"'`\s]*\[\w*\("[^"'`\s]*"\)\])/.source, // bg-[url("...")]
|
|
9
9
|
/([^<>"'`\s]*\[\w*\('[^"`\s]*'\)\])/.source, // bg-[url('...'),url('...')]
|
|
10
10
|
/([^<>"'`\s]*\[\w*\("[^'`\s]*"\)\])/.source, // bg-[url("..."),url("...")]
|
|
11
11
|
/([^<>"'`\s]*\[[^<>"'`\s]*\('[^"`\s]*'\)+\])/.source, // h-[calc(100%-theme('spacing.1'))]
|
|
12
12
|
/([^<>"'`\s]*\[[^<>"'`\s]*\("[^'`\s]*"\)+\])/.source, // h-[calc(100%-theme("spacing.1"))]
|
|
13
|
-
/([
|
|
14
|
-
/([
|
|
13
|
+
/([^${(<>"'`\s]*\['[^"'`\s]*'\])/.source, // `content-['hello']` but not `content-['hello']']`
|
|
14
|
+
/([^${(<>"'`\s]*\["[^"'`\s]*"\])/.source, // `content-["hello"]` but not `content-["hello"]"]`
|
|
15
15
|
/([^<>"'`\s]*\[[^<>"'`\s]*:[^\]\s]*\])/.source, // `[attr:value]`
|
|
16
16
|
/([^<>"'`\s]*\[[^<>"'`\s]*:'[^"'`\s]*'\])/.source, // `[content:'hello']` but not `[content:"hello"]`
|
|
17
17
|
/([^<>"'`\s]*\[[^<>"'`\s]*:"[^"'`\s]*"\])/.source, // `[content:"hello"]` but not `[content:'hello']`
|