tailwindcss 3.4.1 → 3.4.2
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 +22 -2
- package/README.md +2 -3
- package/lib/cli/build/plugin.js +4 -11
- package/lib/cli.js +1 -5
- package/lib/corePluginList.js +1 -0
- package/lib/corePlugins.js +50 -21
- package/lib/css/preflight.css +4 -3
- package/lib/featureFlags.js +2 -6
- package/lib/lib/content.js +36 -3
- package/lib/lib/defaultExtractor.js +2 -2
- package/lib/lib/expandApplyAtRules.js +13 -0
- package/lib/lib/expandTailwindAtRules.js +20 -32
- package/lib/lib/generateRules.js +5 -2
- package/lib/lib/load-config.js +4 -0
- package/lib/lib/offsets.js +51 -2
- package/lib/lib/resolveDefaultsAtRules.js +3 -1
- package/lib/lib/setupContextUtils.js +5 -1
- package/lib/lib/sharedState.js +2 -10
- package/lib/plugin.js +0 -50
- package/lib/processTailwindFeatures.js +0 -2
- package/lib/util/dataTypes.js +1 -1
- package/package.json +5 -8
- package/peers/index.js +61 -61
- package/src/cli/build/plugin.js +4 -11
- package/src/cli.js +1 -5
- package/src/corePluginList.js +1 -1
- package/src/corePlugins.js +45 -23
- package/src/css/preflight.css +4 -3
- package/src/featureFlags.js +2 -6
- package/src/lib/content.js +42 -1
- package/src/lib/defaultExtractor.js +2 -2
- package/src/lib/expandApplyAtRules.js +17 -0
- package/src/lib/expandTailwindAtRules.js +23 -41
- package/src/lib/generateRules.js +2 -2
- package/src/lib/load-config.ts +5 -0
- package/src/lib/offsets.js +61 -2
- package/src/lib/resolveDefaultsAtRules.js +5 -1
- package/src/lib/setupContextUtils.js +6 -1
- package/src/lib/sharedState.js +0 -4
- package/src/plugin.js +0 -60
- package/src/processTailwindFeatures.js +0 -3
- package/src/util/dataTypes.js +1 -1
- package/types/generated/corePluginList.d.ts +1 -1
- package/lib/lib/detectNesting.js +0 -45
- package/lib/oxide/cli/build/deps.js +0 -89
- package/lib/oxide/cli/build/index.js +0 -53
- package/lib/oxide/cli/build/plugin.js +0 -375
- package/lib/oxide/cli/build/utils.js +0 -87
- package/lib/oxide/cli/build/watching.js +0 -179
- package/lib/oxide/cli/help/index.js +0 -72
- package/lib/oxide/cli/index.js +0 -214
- package/lib/oxide/cli/init/index.js +0 -52
- package/lib/oxide/cli.js +0 -5
- package/lib/oxide/postcss-plugin.js +0 -2
- package/scripts/swap-engines.js +0 -40
- package/src/lib/detectNesting.js +0 -47
- package/src/oxide/cli/build/deps.ts +0 -91
- package/src/oxide/cli/build/index.ts +0 -47
- package/src/oxide/cli/build/plugin.ts +0 -442
- package/src/oxide/cli/build/utils.ts +0 -74
- package/src/oxide/cli/build/watching.ts +0 -225
- package/src/oxide/cli/help/index.ts +0 -69
- package/src/oxide/cli/index.ts +0 -204
- package/src/oxide/cli/init/index.ts +0 -59
- package/src/oxide/cli.ts +0 -1
- package/src/oxide/postcss-plugin.ts +0 -1
package/src/cli.js
CHANGED
package/src/corePluginList.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","lineClamp","display","aspectRatio","size","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","captionSide","borderCollapse","borderSpacing","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","listStyleImage","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","hyphens","whitespace","textWrap","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","content","forcedColorAdjust"]
|
|
1
|
+
export default ["preflight","container","accessibility","pointerEvents","visibility","position","inset","isolation","zIndex","order","gridColumn","gridColumnStart","gridColumnEnd","gridRow","gridRowStart","gridRowEnd","float","clear","margin","boxSizing","lineClamp","display","aspectRatio","size","height","maxHeight","minHeight","width","minWidth","maxWidth","flex","flexShrink","flexGrow","flexBasis","tableLayout","captionSide","borderCollapse","borderSpacing","transformOrigin","translate","rotate","skew","scale","transform","animation","cursor","touchAction","userSelect","resize","scrollSnapType","scrollSnapAlign","scrollSnapStop","scrollMargin","scrollPadding","listStylePosition","listStyleType","listStyleImage","appearance","columns","breakBefore","breakInside","breakAfter","gridAutoColumns","gridAutoFlow","gridAutoRows","gridTemplateColumns","gridTemplateRows","flexDirection","flexWrap","placeContent","placeItems","alignContent","alignItems","justifyContent","justifyItems","gap","space","divideWidth","divideStyle","divideColor","divideOpacity","placeSelf","alignSelf","justifySelf","overflow","overscrollBehavior","scrollBehavior","textOverflow","hyphens","whitespace","textWrap","wordBreak","borderRadius","borderWidth","borderStyle","borderColor","borderOpacity","backgroundColor","backgroundOpacity","backgroundImage","gradientColorStops","boxDecorationBreak","backgroundSize","backgroundAttachment","backgroundClip","backgroundPosition","backgroundRepeat","backgroundOrigin","fill","stroke","strokeWidth","objectFit","objectPosition","padding","textAlign","textIndent","verticalAlign","fontFamily","fontSize","fontWeight","textTransform","fontStyle","fontVariantNumeric","lineHeight","letterSpacing","textColor","textOpacity","textDecoration","textDecorationColor","textDecorationStyle","textDecorationThickness","textUnderlineOffset","fontSmoothing","placeholderColor","placeholderOpacity","caretColor","accentColor","opacity","backgroundBlendMode","mixBlendMode","boxShadow","boxShadowColor","outlineStyle","outlineWidth","outlineOffset","outlineColor","ringWidth","ringColor","ringOpacity","ringOffsetWidth","ringOffsetColor","blur","brightness","contrast","dropShadow","grayscale","hueRotate","invert","saturate","sepia","filter","backdropBlur","backdropBrightness","backdropContrast","backdropGrayscale","backdropHueRotate","backdropInvert","backdropOpacity","backdropSaturate","backdropSepia","backdropFilter","transitionProperty","transitionDelay","transitionDuration","transitionTimingFunction","willChange","contain","content","forcedColorAdjust"]
|
package/src/corePlugins.js
CHANGED
|
@@ -270,7 +270,7 @@ export let variantPlugins = {
|
|
|
270
270
|
addVariant('dark', selector)
|
|
271
271
|
} else if (mode === 'class') {
|
|
272
272
|
// Old behavior
|
|
273
|
-
addVariant('dark',
|
|
273
|
+
addVariant('dark', `&:is(${selector} *)`)
|
|
274
274
|
}
|
|
275
275
|
},
|
|
276
276
|
|
|
@@ -1340,16 +1340,6 @@ export let corePlugins = {
|
|
|
1340
1340
|
'space-x': (value) => {
|
|
1341
1341
|
value = value === '0' ? '0px' : value
|
|
1342
1342
|
|
|
1343
|
-
if (__OXIDE__) {
|
|
1344
|
-
return {
|
|
1345
|
-
'& > :not([hidden]) ~ :not([hidden])': {
|
|
1346
|
-
'--tw-space-x-reverse': '0',
|
|
1347
|
-
'margin-inline-end': `calc(${value} * var(--tw-space-x-reverse))`,
|
|
1348
|
-
'margin-inline-start': `calc(${value} * calc(1 - var(--tw-space-x-reverse)))`,
|
|
1349
|
-
},
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
1343
|
return {
|
|
1354
1344
|
'& > :not([hidden]) ~ :not([hidden])': {
|
|
1355
1345
|
'--tw-space-x-reverse': '0',
|
|
@@ -1385,17 +1375,6 @@ export let corePlugins = {
|
|
|
1385
1375
|
'divide-x': (value) => {
|
|
1386
1376
|
value = value === '0' ? '0px' : value
|
|
1387
1377
|
|
|
1388
|
-
if (__OXIDE__) {
|
|
1389
|
-
return {
|
|
1390
|
-
'& > :not([hidden]) ~ :not([hidden])': {
|
|
1391
|
-
'@defaults border-width': {},
|
|
1392
|
-
'--tw-divide-x-reverse': '0',
|
|
1393
|
-
'border-inline-end-width': `calc(${value} * var(--tw-divide-x-reverse))`,
|
|
1394
|
-
'border-inline-start-width': `calc(${value} * calc(1 - var(--tw-divide-x-reverse)))`,
|
|
1395
|
-
},
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
|
|
1399
1378
|
return {
|
|
1400
1379
|
'& > :not([hidden]) ~ :not([hidden])': {
|
|
1401
1380
|
'@defaults border-width': {},
|
|
@@ -2384,6 +2363,7 @@ export let corePlugins = {
|
|
|
2384
2363
|
'.mix-blend-saturation': { 'mix-blend-mode': 'saturation' },
|
|
2385
2364
|
'.mix-blend-color': { 'mix-blend-mode': 'color' },
|
|
2386
2365
|
'.mix-blend-luminosity': { 'mix-blend-mode': 'luminosity' },
|
|
2366
|
+
'.mix-blend-plus-darker': { 'mix-blend-mode': 'plus-darker' },
|
|
2387
2367
|
'.mix-blend-plus-lighter': { 'mix-blend-mode': 'plus-lighter' },
|
|
2388
2368
|
})
|
|
2389
2369
|
},
|
|
@@ -2397,7 +2377,7 @@ export let corePlugins = {
|
|
|
2397
2377
|
].join(', ')
|
|
2398
2378
|
|
|
2399
2379
|
return function ({ matchUtilities, addDefaults, theme }) {
|
|
2400
|
-
addDefaults('
|
|
2380
|
+
addDefaults('box-shadow', {
|
|
2401
2381
|
'--tw-ring-offset-shadow': '0 0 #0000',
|
|
2402
2382
|
'--tw-ring-shadow': '0 0 #0000',
|
|
2403
2383
|
'--tw-shadow': '0 0 #0000',
|
|
@@ -2931,6 +2911,48 @@ export let corePlugins = {
|
|
|
2931
2911
|
{ filterDefault: true }
|
|
2932
2912
|
),
|
|
2933
2913
|
willChange: createUtilityPlugin('willChange', [['will-change', ['will-change']]]),
|
|
2914
|
+
contain: ({ addDefaults, addUtilities }) => {
|
|
2915
|
+
let cssContainValue =
|
|
2916
|
+
'var(--tw-contain-size) var(--tw-contain-layout) var(--tw-contain-paint) var(--tw-contain-style)'
|
|
2917
|
+
|
|
2918
|
+
addDefaults('contain', {
|
|
2919
|
+
'--tw-contain-size': ' ',
|
|
2920
|
+
'--tw-contain-layout': ' ',
|
|
2921
|
+
'--tw-contain-paint': ' ',
|
|
2922
|
+
'--tw-contain-style': ' ',
|
|
2923
|
+
})
|
|
2924
|
+
|
|
2925
|
+
addUtilities({
|
|
2926
|
+
'.contain-none': { contain: 'none' },
|
|
2927
|
+
'.contain-content': { contain: 'content' },
|
|
2928
|
+
'.contain-strict': { contain: 'strict' },
|
|
2929
|
+
'.contain-size': {
|
|
2930
|
+
'@defaults contain': {},
|
|
2931
|
+
'--tw-contain-size': 'size',
|
|
2932
|
+
contain: cssContainValue,
|
|
2933
|
+
},
|
|
2934
|
+
'.contain-inline-size': {
|
|
2935
|
+
'@defaults contain': {},
|
|
2936
|
+
'--tw-contain-size': 'inline-size',
|
|
2937
|
+
contain: cssContainValue,
|
|
2938
|
+
},
|
|
2939
|
+
'.contain-layout': {
|
|
2940
|
+
'@defaults contain': {},
|
|
2941
|
+
'--tw-contain-layout': 'layout',
|
|
2942
|
+
contain: cssContainValue,
|
|
2943
|
+
},
|
|
2944
|
+
'.contain-paint': {
|
|
2945
|
+
'@defaults contain': {},
|
|
2946
|
+
'--tw-contain-paint': 'paint',
|
|
2947
|
+
contain: cssContainValue,
|
|
2948
|
+
},
|
|
2949
|
+
'.contain-style': {
|
|
2950
|
+
'@defaults contain': {},
|
|
2951
|
+
'--tw-contain-style': 'style',
|
|
2952
|
+
contain: cssContainValue,
|
|
2953
|
+
},
|
|
2954
|
+
})
|
|
2955
|
+
},
|
|
2934
2956
|
content: createUtilityPlugin('content', [
|
|
2935
2957
|
['content', ['--tw-content', ['content', 'var(--tw-content)']]],
|
|
2936
2958
|
]),
|
package/src/css/preflight.css
CHANGED
|
@@ -175,6 +175,7 @@ textarea {
|
|
|
175
175
|
font-size: 100%; /* 1 */
|
|
176
176
|
font-weight: inherit; /* 1 */
|
|
177
177
|
line-height: inherit; /* 1 */
|
|
178
|
+
letter-spacing: inherit; /* 1 */
|
|
178
179
|
color: inherit; /* 1 */
|
|
179
180
|
margin: 0; /* 2 */
|
|
180
181
|
padding: 0; /* 3 */
|
|
@@ -195,9 +196,9 @@ select {
|
|
|
195
196
|
*/
|
|
196
197
|
|
|
197
198
|
button,
|
|
198
|
-
[type='button'],
|
|
199
|
-
[type='reset'],
|
|
200
|
-
[type='submit'] {
|
|
199
|
+
input:where([type='button']),
|
|
200
|
+
input:where([type='reset']),
|
|
201
|
+
input:where([type='submit']) {
|
|
201
202
|
-webkit-appearance: button; /* 1 */
|
|
202
203
|
background-color: transparent; /* 2 */
|
|
203
204
|
background-image: none; /* 2 */
|
package/src/featureFlags.js
CHANGED
|
@@ -4,12 +4,8 @@ import log from './util/log'
|
|
|
4
4
|
let defaults = {
|
|
5
5
|
optimizeUniversalDefaults: false,
|
|
6
6
|
generalizedModifiers: true,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
get relativeContentPathsByDefault() {
|
|
11
|
-
return __OXIDE__
|
|
12
|
-
},
|
|
7
|
+
disableColorOpacityUtilitiesByDefault: false,
|
|
8
|
+
relativeContentPathsByDefault: false,
|
|
13
9
|
}
|
|
14
10
|
|
|
15
11
|
let featureFlags = {
|
package/src/lib/content.js
CHANGED
|
@@ -4,10 +4,47 @@ import fs from 'fs'
|
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import isGlob from 'is-glob'
|
|
6
6
|
import fastGlob from 'fast-glob'
|
|
7
|
-
import normalizePath from 'normalize-path'
|
|
8
7
|
import { parseGlob } from '../util/parseGlob'
|
|
9
8
|
import { env } from './sharedState'
|
|
10
9
|
|
|
10
|
+
/*!
|
|
11
|
+
* Modified version of normalize-path, original license below
|
|
12
|
+
*
|
|
13
|
+
* normalize-path <https://github.com/jonschlinkert/normalize-path>
|
|
14
|
+
*
|
|
15
|
+
* Copyright (c) 2014-2018, Jon Schlinkert.
|
|
16
|
+
* Released under the MIT License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
function normalizePath(path) {
|
|
20
|
+
if (typeof path !== 'string') {
|
|
21
|
+
throw new TypeError('expected path to be a string')
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (path === '\\' || path === '/') return '/'
|
|
25
|
+
|
|
26
|
+
var len = path.length
|
|
27
|
+
if (len <= 1) return path
|
|
28
|
+
|
|
29
|
+
// ensure that win32 namespaces has two leading slashes, so that the path is
|
|
30
|
+
// handled properly by the win32 version of path.parse() after being normalized
|
|
31
|
+
// https://msdn.microsoft.com/library/windows/desktop/aa365247(v=vs.85).aspx#namespaces
|
|
32
|
+
var prefix = ''
|
|
33
|
+
if (len > 4 && path[3] === '\\') {
|
|
34
|
+
var ch = path[2]
|
|
35
|
+
if ((ch === '?' || ch === '.') && path.slice(0, 2) === '\\\\') {
|
|
36
|
+
path = path.slice(2)
|
|
37
|
+
prefix = '//'
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Modified part: instead of purely splitting on `\\` and `/`, we split on
|
|
42
|
+
// `/` and `\\` that is _not_ followed by any of the following characters: ()[]
|
|
43
|
+
// This is to ensure that we keep the escaping of brackets and parentheses
|
|
44
|
+
let segs = path.split(/[/\\]+(?![\(\)\[\]])/)
|
|
45
|
+
return prefix + segs.join('/')
|
|
46
|
+
}
|
|
47
|
+
|
|
11
48
|
/** @typedef {import('../../types/config.js').RawFile} RawFile */
|
|
12
49
|
/** @typedef {import('../../types/config.js').FilePath} FilePath */
|
|
13
50
|
|
|
@@ -73,6 +110,10 @@ export function parseCandidateFiles(context, tailwindConfig) {
|
|
|
73
110
|
* @returns {ContentPath}
|
|
74
111
|
*/
|
|
75
112
|
function parseFilePath(filePath, ignore) {
|
|
113
|
+
// Escape special characters in the file path such as: ()[]
|
|
114
|
+
// But only if the special character isn't already escaped
|
|
115
|
+
filePath = filePath.replace(/(?<!\\)([\[\]\(\)])/g, '\\$1')
|
|
116
|
+
|
|
76
117
|
let contentPath = {
|
|
77
118
|
original: filePath,
|
|
78
119
|
base: filePath,
|
|
@@ -96,7 +96,7 @@ function* buildRegExps(context) {
|
|
|
96
96
|
regex.pattern([/@\[[^\s"'`]+\](\/[^\s"'`]+)?/, separator]),
|
|
97
97
|
|
|
98
98
|
// With variant modifier (e.g.: group-[..]/modifier)
|
|
99
|
-
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]
|
|
99
|
+
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]\/[\w_-]+/, separator]),
|
|
100
100
|
|
|
101
101
|
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s"'`]+\]/, separator]),
|
|
102
102
|
regex.pattern([/[^\s"'`\[\\]+/, separator]),
|
|
@@ -105,7 +105,7 @@ function* buildRegExps(context) {
|
|
|
105
105
|
// With quotes allowed
|
|
106
106
|
regex.any([
|
|
107
107
|
// With variant modifier (e.g.: group-[..]/modifier)
|
|
108
|
-
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]
|
|
108
|
+
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]\/[\w_-]+/, separator]),
|
|
109
109
|
|
|
110
110
|
regex.pattern([/([^\s"'`\[\\]+-)?\[[^\s`]+\]/, separator]),
|
|
111
111
|
regex.pattern([/[^\s`\[\\]+/, separator]),
|
|
@@ -432,6 +432,23 @@ function processApply(root, context, localCache) {
|
|
|
432
432
|
|
|
433
433
|
let rules = applyClassCache.get(applyCandidate)
|
|
434
434
|
|
|
435
|
+
// Verify that we can apply the class
|
|
436
|
+
for (let [, rule] of rules) {
|
|
437
|
+
if (rule.type === 'atrule') {
|
|
438
|
+
continue
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
rule.walkRules(() => {
|
|
442
|
+
throw apply.error(
|
|
443
|
+
[
|
|
444
|
+
`The \`${applyCandidate}\` class cannot be used with \`@apply\` because \`@apply\` does not currently support nested CSS.`,
|
|
445
|
+
'Rewrite the selector without nesting or configure the `tailwindcss/nesting` plugin:',
|
|
446
|
+
'https://tailwindcss.com/docs/using-with-preprocessors#nesting',
|
|
447
|
+
].join('\n')
|
|
448
|
+
)
|
|
449
|
+
})
|
|
450
|
+
}
|
|
451
|
+
|
|
435
452
|
candidates.push([applyCandidate, important, rules])
|
|
436
453
|
}
|
|
437
454
|
}
|
|
@@ -130,41 +130,25 @@ export default function expandTailwindAtRules(context) {
|
|
|
130
130
|
|
|
131
131
|
env.DEBUG && console.time('Reading changed files')
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
for (let candidate of require('@tailwindcss/oxide').parseCandidateStringsFromFiles(
|
|
136
|
-
context.changedContent
|
|
137
|
-
// Object.assign({}, builtInTransformers, context.tailwindConfig.content.transform)
|
|
138
|
-
)) {
|
|
139
|
-
candidates.add(candidate)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// for (let { file, content, extension } of context.changedContent) {
|
|
143
|
-
// let transformer = getTransformer(context.tailwindConfig, extension)
|
|
144
|
-
// let extractor = getExtractor(context, extension)
|
|
145
|
-
// getClassCandidatesOxide(file, transformer(content), extractor, candidates, seen)
|
|
146
|
-
// }
|
|
147
|
-
} else {
|
|
148
|
-
/** @type {[item: {file?: string, content?: string}, meta: {transformer: any, extractor: any}][]} */
|
|
149
|
-
let regexParserContent = []
|
|
133
|
+
/** @type {[item: {file?: string, content?: string}, meta: {transformer: any, extractor: any}][]} */
|
|
134
|
+
let regexParserContent = []
|
|
150
135
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
136
|
+
for (let item of context.changedContent) {
|
|
137
|
+
let transformer = getTransformer(context.tailwindConfig, item.extension)
|
|
138
|
+
let extractor = getExtractor(context, item.extension)
|
|
139
|
+
regexParserContent.push([item, { transformer, extractor }])
|
|
140
|
+
}
|
|
156
141
|
|
|
157
|
-
|
|
142
|
+
const BATCH_SIZE = 500
|
|
158
143
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
144
|
+
for (let i = 0; i < regexParserContent.length; i += BATCH_SIZE) {
|
|
145
|
+
let batch = regexParserContent.slice(i, i + BATCH_SIZE)
|
|
146
|
+
await Promise.all(
|
|
147
|
+
batch.map(async ([{ file, content }, { transformer, extractor }]) => {
|
|
148
|
+
content = file ? await fs.promises.readFile(file, 'utf8') : content
|
|
149
|
+
getClassCandidates(transformer(content), extractor, candidates, seen)
|
|
150
|
+
})
|
|
151
|
+
)
|
|
168
152
|
}
|
|
169
153
|
|
|
170
154
|
env.DEBUG && console.timeEnd('Reading changed files')
|
|
@@ -176,15 +160,13 @@ export default function expandTailwindAtRules(context) {
|
|
|
176
160
|
|
|
177
161
|
env.DEBUG && console.time('Generate rules')
|
|
178
162
|
env.DEBUG && console.time('Sorting candidates')
|
|
179
|
-
let sortedCandidates =
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
})
|
|
187
|
-
)
|
|
163
|
+
let sortedCandidates = new Set(
|
|
164
|
+
[...candidates].sort((a, z) => {
|
|
165
|
+
if (a === z) return 0
|
|
166
|
+
if (a < z) return -1
|
|
167
|
+
return 1
|
|
168
|
+
})
|
|
169
|
+
)
|
|
188
170
|
env.DEBUG && console.timeEnd('Sorting candidates')
|
|
189
171
|
generateRules(sortedCandidates, context)
|
|
190
172
|
env.DEBUG && console.timeEnd('Generate rules')
|
package/src/lib/generateRules.js
CHANGED
|
@@ -512,11 +512,11 @@ function extractArbitraryProperty(classCandidate, context) {
|
|
|
512
512
|
return null
|
|
513
513
|
}
|
|
514
514
|
|
|
515
|
-
let sort = context.offsets.arbitraryProperty()
|
|
515
|
+
let sort = context.offsets.arbitraryProperty(classCandidate)
|
|
516
516
|
|
|
517
517
|
return [
|
|
518
518
|
[
|
|
519
|
-
{ sort, layer: 'utilities' },
|
|
519
|
+
{ sort, layer: 'utilities', options: { respectImportant: true } },
|
|
520
520
|
() => ({
|
|
521
521
|
[asClass(classCandidate)]: {
|
|
522
522
|
[property]: normalized,
|
package/src/lib/load-config.ts
CHANGED
|
@@ -18,6 +18,11 @@ function lazyJiti() {
|
|
|
18
18
|
(jiti = jitiFactory(__filename, {
|
|
19
19
|
interopDefault: true,
|
|
20
20
|
transform: (opts) => {
|
|
21
|
+
// Sucrase can't transform import.meta so we have to use Babel
|
|
22
|
+
if (opts.source.includes('import.meta')) {
|
|
23
|
+
return require('jiti/dist/babel.js')(opts)
|
|
24
|
+
}
|
|
25
|
+
|
|
21
26
|
return transform(opts.source, {
|
|
22
27
|
transforms: ['typescript', 'imports'],
|
|
23
28
|
})
|
package/src/lib/offsets.js
CHANGED
|
@@ -23,7 +23,9 @@ import { remapBitfield } from './remap-bitfield.js'
|
|
|
23
23
|
* @property {bigint} arbitrary 0n if false, 1n if true
|
|
24
24
|
* @property {bigint} variants Dynamic size. 1 bit per registered variant. 0n means no variants
|
|
25
25
|
* @property {bigint} parallelIndex Rule index for the parallel variant. 0 if not applicable.
|
|
26
|
-
* @property {bigint} index Index of the rule / utility in
|
|
26
|
+
* @property {bigint} index Index of the rule / utility in its given *parent* layer. Monotonically increasing.
|
|
27
|
+
* @property {bigint} propertyOffset Offset for the arbitrary property. Only valid after sorting.
|
|
28
|
+
* @property {string} property Name/Value of the arbitrary property.
|
|
27
29
|
* @property {VariantOption[]} options Some information on how we can sort arbitrary variants
|
|
28
30
|
*/
|
|
29
31
|
|
|
@@ -88,17 +90,21 @@ export class Offsets {
|
|
|
88
90
|
variants: 0n,
|
|
89
91
|
parallelIndex: 0n,
|
|
90
92
|
index: this.offsets[layer]++,
|
|
93
|
+
propertyOffset: 0n,
|
|
94
|
+
property: '',
|
|
91
95
|
options: [],
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
/**
|
|
100
|
+
* @param {string} name
|
|
96
101
|
* @returns {RuleOffset}
|
|
97
102
|
*/
|
|
98
|
-
arbitraryProperty() {
|
|
103
|
+
arbitraryProperty(name) {
|
|
99
104
|
return {
|
|
100
105
|
...this.create('utilities'),
|
|
101
106
|
arbitrary: 1n,
|
|
107
|
+
property: name,
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
110
|
|
|
@@ -262,6 +268,11 @@ export class Offsets {
|
|
|
262
268
|
return a.arbitrary - b.arbitrary
|
|
263
269
|
}
|
|
264
270
|
|
|
271
|
+
// Always sort arbitrary properties alphabetically
|
|
272
|
+
if (a.propertyOffset !== b.propertyOffset) {
|
|
273
|
+
return a.propertyOffset - b.propertyOffset
|
|
274
|
+
}
|
|
275
|
+
|
|
265
276
|
// Sort utilities, components, etc… in the order they were registered
|
|
266
277
|
return a.index - b.index
|
|
267
278
|
}
|
|
@@ -320,14 +331,62 @@ export class Offsets {
|
|
|
320
331
|
})
|
|
321
332
|
}
|
|
322
333
|
|
|
334
|
+
/**
|
|
335
|
+
* @template T
|
|
336
|
+
* @param {[RuleOffset, T][]} list
|
|
337
|
+
* @returns {[RuleOffset, T][]}
|
|
338
|
+
*/
|
|
339
|
+
sortArbitraryProperties(list) {
|
|
340
|
+
// Collect all known arbitrary properties
|
|
341
|
+
let known = new Set()
|
|
342
|
+
|
|
343
|
+
for (let [offset] of list) {
|
|
344
|
+
if (offset.arbitrary === 1n) {
|
|
345
|
+
known.add(offset.property)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// No arbitrary properties? Nothing to do.
|
|
350
|
+
if (known.size === 0) {
|
|
351
|
+
return list
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// Sort the properties alphabetically
|
|
355
|
+
let properties = Array.from(known).sort()
|
|
356
|
+
|
|
357
|
+
// Create a map from the property name to its offset
|
|
358
|
+
let offsets = new Map()
|
|
359
|
+
|
|
360
|
+
let offset = 1n
|
|
361
|
+
for (let property of properties) {
|
|
362
|
+
offsets.set(property, offset++)
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Apply the sorted offsets to the list
|
|
366
|
+
return list.map((item) => {
|
|
367
|
+
let [offset, rule] = item
|
|
368
|
+
|
|
369
|
+
offset = {
|
|
370
|
+
...offset,
|
|
371
|
+
propertyOffset: offsets.get(offset.property) ?? 0n,
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return [offset, rule]
|
|
375
|
+
})
|
|
376
|
+
}
|
|
377
|
+
|
|
323
378
|
/**
|
|
324
379
|
* @template T
|
|
325
380
|
* @param {[RuleOffset, T][]} list
|
|
326
381
|
* @returns {[RuleOffset, T][]}
|
|
327
382
|
*/
|
|
328
383
|
sort(list) {
|
|
384
|
+
// Sort arbitrary variants so they're in alphabetical order
|
|
329
385
|
list = this.remapArbitraryVariantOffsets(list)
|
|
330
386
|
|
|
387
|
+
// Sort arbitrary properties so they're in alphabetical order
|
|
388
|
+
list = this.sortArbitraryProperties(list)
|
|
389
|
+
|
|
331
390
|
return list.sort(([a], [b]) => bigSign(this.compare(a, b)))
|
|
332
391
|
}
|
|
333
392
|
}
|
|
@@ -104,8 +104,12 @@ export default function resolveDefaultsAtRules({ tailwindConfig }) {
|
|
|
104
104
|
// we consider them separately because merging the declarations into
|
|
105
105
|
// a single rule will cause browsers that do not understand the
|
|
106
106
|
// vendor prefix to throw out the whole rule
|
|
107
|
+
// Additionally if a selector contains `:has` we also consider
|
|
108
|
+
// it separately because FF only recently gained support for it
|
|
107
109
|
let selectorGroupName =
|
|
108
|
-
selector.includes(':-') || selector.includes('::-')
|
|
110
|
+
selector.includes(':-') || selector.includes('::-') || selector.includes(':has')
|
|
111
|
+
? selector
|
|
112
|
+
: '__DEFAULT__'
|
|
109
113
|
|
|
110
114
|
let selectors = selectorGroups.get(selectorGroupName) ?? new Set()
|
|
111
115
|
selectorGroups.set(selectorGroupName, selectors)
|
|
@@ -1044,6 +1044,11 @@ function registerPlugins(plugins, context) {
|
|
|
1044
1044
|
|
|
1045
1045
|
// Generate a list of available variants with meta information of the type of variant.
|
|
1046
1046
|
context.getVariants = function getVariants() {
|
|
1047
|
+
// We use a unique, random ID for candidate names to avoid conflicts
|
|
1048
|
+
// We can't use characters like `_`, `:`, `@` or `.` because they might
|
|
1049
|
+
// be used as a separator
|
|
1050
|
+
let id = Math.random().toString(36).substring(7).toUpperCase()
|
|
1051
|
+
|
|
1047
1052
|
let result = []
|
|
1048
1053
|
for (let [name, options] of context.variantOptions.entries()) {
|
|
1049
1054
|
if (options.variantInfo === VARIANT_INFO.Base) continue
|
|
@@ -1054,7 +1059,7 @@ function registerPlugins(plugins, context) {
|
|
|
1054
1059
|
values: Object.keys(options.values ?? {}),
|
|
1055
1060
|
hasDash: name !== '@',
|
|
1056
1061
|
selectors({ modifier, value } = {}) {
|
|
1057
|
-
let candidate =
|
|
1062
|
+
let candidate = `TAILWINDPLACEHOLDER${id}`
|
|
1058
1063
|
|
|
1059
1064
|
let rule = postcss.rule({ selector: `.${candidate}` })
|
|
1060
1065
|
let container = postcss.root({ nodes: [rule.clone()] })
|
package/src/lib/sharedState.js
CHANGED
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import pkg from '../../package.json'
|
|
2
|
-
|
|
3
1
|
export const env =
|
|
4
2
|
typeof process !== 'undefined'
|
|
5
3
|
? {
|
|
6
4
|
NODE_ENV: process.env.NODE_ENV,
|
|
7
5
|
DEBUG: resolveDebug(process.env.DEBUG),
|
|
8
|
-
ENGINE: pkg.tailwindcss.engine,
|
|
9
6
|
}
|
|
10
7
|
: {
|
|
11
8
|
NODE_ENV: 'production',
|
|
12
9
|
DEBUG: false,
|
|
13
|
-
ENGINE: pkg.tailwindcss.engine,
|
|
14
10
|
}
|
|
15
11
|
|
|
16
12
|
export const contextMap = new Map()
|
package/src/plugin.js
CHANGED
|
@@ -34,66 +34,6 @@ module.exports = function tailwindcss(configOrPath) {
|
|
|
34
34
|
|
|
35
35
|
await processTailwindFeatures(context)(root, result)
|
|
36
36
|
},
|
|
37
|
-
__OXIDE__ &&
|
|
38
|
-
function lightningCssPlugin(_root, result) {
|
|
39
|
-
let postcss = require('postcss')
|
|
40
|
-
let lightningcss = require('lightningcss')
|
|
41
|
-
let browserslist = require('browserslist')
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
let transformed = lightningcss.transform({
|
|
45
|
-
filename: result.opts.from,
|
|
46
|
-
code: Buffer.from(result.root.toString()),
|
|
47
|
-
minify: false,
|
|
48
|
-
sourceMap: !!result.map,
|
|
49
|
-
inputSourceMap: result.map ? result.map.toString() : undefined,
|
|
50
|
-
targets:
|
|
51
|
-
typeof process !== 'undefined' && process.env.JEST_WORKER_ID
|
|
52
|
-
? { chrome: 106 << 16 }
|
|
53
|
-
: lightningcss.browserslistToTargets(
|
|
54
|
-
browserslist(require('../package.json').browserslist)
|
|
55
|
-
),
|
|
56
|
-
|
|
57
|
-
drafts: {
|
|
58
|
-
nesting: true,
|
|
59
|
-
customMedia: true,
|
|
60
|
-
},
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
result.map = Object.assign(result.map ?? {}, {
|
|
64
|
-
toJSON() {
|
|
65
|
-
return transformed.map.toJSON()
|
|
66
|
-
},
|
|
67
|
-
toString() {
|
|
68
|
-
return transformed.map.toString()
|
|
69
|
-
},
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
result.root = postcss.parse(transformed.code.toString('utf8'))
|
|
73
|
-
} catch (err) {
|
|
74
|
-
if (typeof process !== 'undefined' && process.env.JEST_WORKER_ID) {
|
|
75
|
-
let lines = err.source.split('\n')
|
|
76
|
-
err = new Error(
|
|
77
|
-
[
|
|
78
|
-
'Error formatting using Lightning CSS:',
|
|
79
|
-
'',
|
|
80
|
-
...[
|
|
81
|
-
'```css',
|
|
82
|
-
...lines.slice(Math.max(err.loc.line - 3, 0), err.loc.line),
|
|
83
|
-
' '.repeat(err.loc.column - 1) + '^-- ' + err.toString(),
|
|
84
|
-
...lines.slice(err.loc.line, err.loc.line + 2),
|
|
85
|
-
'```',
|
|
86
|
-
],
|
|
87
|
-
].join('\n')
|
|
88
|
-
)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (Error.captureStackTrace) {
|
|
92
|
-
Error.captureStackTrace(err, lightningCssPlugin)
|
|
93
|
-
}
|
|
94
|
-
throw err
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
37
|
env.DEBUG &&
|
|
98
38
|
function (root) {
|
|
99
39
|
console.timeEnd('JIT TOTAL')
|
|
@@ -7,7 +7,6 @@ import resolveDefaultsAtRules from './lib/resolveDefaultsAtRules'
|
|
|
7
7
|
import collapseAdjacentRules from './lib/collapseAdjacentRules'
|
|
8
8
|
import collapseDuplicateDeclarations from './lib/collapseDuplicateDeclarations'
|
|
9
9
|
import partitionApplyAtRules from './lib/partitionApplyAtRules'
|
|
10
|
-
import detectNesting from './lib/detectNesting'
|
|
11
10
|
import { createContext } from './lib/setupContextUtils'
|
|
12
11
|
import { issueFlagNotices } from './featureFlags'
|
|
13
12
|
|
|
@@ -15,8 +14,6 @@ export default function processTailwindFeatures(setupContext) {
|
|
|
15
14
|
return async function (root, result) {
|
|
16
15
|
let { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root)
|
|
17
16
|
|
|
18
|
-
detectNesting()(root, result)
|
|
19
|
-
|
|
20
17
|
// Partition apply rules that are found in the css
|
|
21
18
|
// itself.
|
|
22
19
|
partitionApplyAtRules()(root, result)
|