Skip to content

Commit b0128bf

Browse files
committed
implement parallel variants
1 parent 7ae608a commit b0128bf

File tree

4 files changed

+85
-40
lines changed

4 files changed

+85
-40
lines changed

src/jit/corePlugins.js

+20-8
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,35 @@ export default {
3030
})
3131
)
3232

33-
addVariant(
34-
'marker',
33+
addVariant('marker', [
34+
transformAllSelectors((selector) => {
35+
let variantSelector = updateAllClasses(selector, (className) => {
36+
return `marker${config('separator')}${className}`
37+
})
38+
39+
return `${variantSelector} *::marker`
40+
}),
3541
transformAllSelectors((selector) => {
3642
return updateAllClasses(selector, (className, { withPseudo }) => {
3743
return withPseudo(`marker${config('separator')}${className}`, '::marker')
3844
})
39-
})
40-
)
45+
}),
46+
])
4147

42-
addVariant(
43-
'selection',
48+
addVariant('selection', [
49+
transformAllSelectors((selector) => {
50+
let variantSelector = updateAllClasses(selector, (className) => {
51+
return `selection${config('separator')}${className}`
52+
})
53+
54+
return `${variantSelector} *::selection`
55+
}),
4456
transformAllSelectors((selector) => {
4557
return updateAllClasses(selector, (className, { withPseudo }) => {
4658
return withPseudo(`selection${config('separator')}${className}`, '::selection')
4759
})
48-
})
49-
)
60+
}),
61+
])
5062

5163
addVariant(
5264
'before',

src/jit/lib/generateRules.js

+28-25
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ function applyVariant(variant, matches, context) {
100100
}
101101

102102
if (context.variantMap.has(variant)) {
103-
let [variantSort, applyThisVariant] = context.variantMap.get(variant)
103+
let variantFunctionTuples = context.variantMap.get(variant)
104104
let result = []
105105

106106
for (let [{ sort, layer, options }, rule] of matches) {
@@ -112,36 +112,39 @@ function applyVariant(variant, matches, context) {
112112
let container = postcss.root()
113113
container.append(rule.clone())
114114

115-
function modifySelectors(modifierFunction) {
116-
container.each((rule) => {
117-
if (rule.type !== 'rule') {
118-
return
119-
}
120-
121-
rule.selectors = rule.selectors.map((selector) => {
122-
return modifierFunction({
123-
get className() {
124-
return getClassNameFromSelector(selector)
125-
},
126-
selector,
115+
for (let [variantSort, variantFunction] of variantFunctionTuples) {
116+
let clone = container.clone()
117+
function modifySelectors(modifierFunction) {
118+
clone.each((rule) => {
119+
if (rule.type !== 'rule') {
120+
return
121+
}
122+
123+
rule.selectors = rule.selectors.map((selector) => {
124+
return modifierFunction({
125+
get className() {
126+
return getClassNameFromSelector(selector)
127+
},
128+
selector,
129+
})
127130
})
128131
})
132+
return clone
133+
}
134+
135+
let ruleWithVariant = variantFunction({
136+
container: clone,
137+
separator: context.tailwindConfig.separator,
138+
modifySelectors,
129139
})
130-
return container
131-
}
132140

133-
let ruleWithVariant = applyThisVariant({
134-
container,
135-
separator: context.tailwindConfig.separator,
136-
modifySelectors,
137-
})
141+
if (ruleWithVariant === null) {
142+
continue
143+
}
138144

139-
if (ruleWithVariant === null) {
140-
continue
145+
let withOffset = [{ sort: variantSort | sort, layer, options }, clone.nodes[0]]
146+
result.push(withOffset)
141147
}
142-
143-
let withOffset = [{ sort: variantSort | sort, layer, options }, container.nodes[0]]
144-
result.push(withOffset)
145148
}
146149

147150
return result

src/jit/lib/setupContextUtils.js

+21-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import isPlainObject from '../../util/isPlainObject'
1313
import escapeClassName from '../../util/escapeClassName'
1414
import nameClass from '../../util/nameClass'
1515
import { coerceValue } from '../../util/pluginUtils'
16+
import bigSign from '../../util/bigSign'
1617
import corePlugins from '../corePlugins'
1718
import * as sharedState from './sharedState'
1819
import { env } from './sharedState'
@@ -152,9 +153,11 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
152153
}
153154

154155
return {
155-
addVariant(variantName, applyThisVariant, options = {}) {
156+
addVariant(variantName, variantFunctions, options = {}) {
157+
variantFunctions = [].concat(variantFunctions)
158+
156159
insertInto(variantList, variantName, options)
157-
variantMap.set(variantName, applyThisVariant)
160+
variantMap.set(variantName, variantFunctions)
158161
},
159162
postcss,
160163
prefix: applyConfiguredPrefix,
@@ -445,17 +448,28 @@ function registerPlugins(plugins, context) {
445448
}
446449

447450
reservedBits += 3n
448-
context.variantOrder = variantList.reduce(
449-
(map, variant, i) => map.set(variant, (1n << BigInt(i)) << reservedBits),
450-
new Map()
451+
452+
let offset = 0
453+
context.variantOrder = new Map(
454+
variantList
455+
.map((variant, i) => {
456+
let variantFunctions = variantMap.get(variant).length
457+
let bits = (1n << BigInt(i + offset)) << reservedBits
458+
offset += variantFunctions - 1
459+
return [variant, bits]
460+
})
461+
.sort(([, a], [, z]) => bigSign(a - z))
451462
)
452463

453464
context.minimumScreen = [...context.variantOrder.values()].shift()
454465

455466
// Build variantMap
456-
for (let [variantName, variantFunction] of variantMap.entries()) {
467+
for (let [variantName, variantFunctions] of variantMap.entries()) {
457468
let sort = context.variantOrder.get(variantName)
458-
context.variantMap.set(variantName, [sort, variantFunction])
469+
context.variantMap.set(
470+
variantName,
471+
variantFunctions.map((variantFunction, idx) => [sort << BigInt(idx), variantFunction])
472+
)
459473
}
460474
}
461475

tests/jit/variants.test.css

+16
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
.first-line\:underline::first-line {
2929
text-decoration: underline;
3030
}
31+
.marker\:text-lg *::marker {
32+
font-size: 1.125rem;
33+
line-height: 1.75rem;
34+
}
35+
.marker\:text-red-500 *::marker {
36+
--tw-text-opacity: 1;
37+
color: rgba(239, 68, 68, var(--tw-text-opacity));
38+
}
3139
.marker\:text-lg::marker {
3240
font-size: 1.125rem;
3341
line-height: 1.75rem;
@@ -36,6 +44,14 @@
3644
--tw-text-opacity: 1;
3745
color: rgba(239, 68, 68, var(--tw-text-opacity));
3846
}
47+
.selection\:bg-blue-500 *::selection {
48+
--tw-bg-opacity: 1;
49+
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));
50+
}
51+
.selection\:text-white *::selection {
52+
--tw-text-opacity: 1;
53+
color: rgba(255, 255, 255, var(--tw-text-opacity));
54+
}
3955
.selection\:bg-blue-500::selection {
4056
--tw-bg-opacity: 1;
4157
background-color: rgba(59, 130, 246, var(--tw-bg-opacity));

0 commit comments

Comments
 (0)