Skip to content

Commit 0c5c540

Browse files
Improve matchUtilities API and make it work with the AOT engine (#4232)
* implement matchUtilities2 * ensure animation names without keyframes are not prefixed * remove matchBase * call addUtilities for each group individually * WIP: Write plugins using matchUtilities2 * MORE * Fix arbitrary value support for fontSize * Fixes, update fixtures * Rebuild fixtures * Don't generate `divide` class with no modifier * Fixes, rebuild fixtures * Rename matchUtilities2 to matchUtilities * Delete bad tests * Remove temp files GROSS * Clean stuff up * Support no return in matchUtilities Co-authored-by: Adam Wathan <[email protected]>
1 parent e8d2619 commit 0c5c540

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+72355
-73566
lines changed

src/jit/lib/generateRules.js

+1-6
Original file line numberDiff line numberDiff line change
@@ -215,17 +215,12 @@ function* resolveMatches(candidate, context) {
215215
// }
216216

217217
for (let matchedPlugins of resolveMatchedPlugins(classCandidate, context)) {
218-
let pluginHelpers = {
219-
candidate: classCandidate,
220-
theme: context.tailwindConfig.theme,
221-
}
222-
223218
let matches = []
224219
let [plugins, modifier] = matchedPlugins
225220

226221
for (let [sort, plugin] of plugins) {
227222
if (typeof plugin === 'function') {
228-
for (let ruleSet of [].concat(plugin(modifier, pluginHelpers))) {
223+
for (let ruleSet of [].concat(plugin(modifier))) {
229224
let [rules, options] = parseRules(ruleSet, context.postCssNodeCache)
230225
for (let rule of rules) {
231226
matches.push([{ ...sort, options: { ...sort.options, ...options } }, rule])

src/jit/lib/setupContext.js

+29-40
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ import corePlugins from '../corePlugins'
2222
import isPlainObject from '../../util/isPlainObject'
2323
import escapeClassName from '../../util/escapeClassName'
2424

25+
import nameClass from '../../util/nameClass'
26+
import { coerceValue } from '../../util/pluginUtils'
27+
2528
import * as sharedState from './sharedState'
2629

2730
let contextMap = sharedState.contextMap
@@ -513,36 +516,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
513516
.push([{ sort: offset, layer: 'utilities', options }, rule])
514517
}
515518
},
516-
matchBase: function (base) {
517-
let offset = offsets.base++
518-
519-
for (let identifier in base) {
520-
let prefixedIdentifier = prefixIdentifier(identifier, options)
521-
let rule = base[identifier]
522-
523-
let withOffsets = [{ sort: offset, layer: 'base' }, rule]
524-
525-
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
526-
context.candidateRuleMap.set(prefixedIdentifier, [])
527-
}
528-
529-
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
530-
}
531-
},
532519
matchUtilities: function (utilities, options) {
533-
// TODO: Redesign this API to work like this so it's more end-user friendly
534-
// matchUtilities({
535-
// animate: (value, { includeRules }) => {
536-
// let { name: animationName } = parseAnimationValue(value)
537-
538-
// if (keyframes[animationName] !== undefined) {
539-
// includeRules(keyframes[animationName])
540-
// }
541-
542-
// return { animation: value }
543-
// },
544-
// }, { values: [...], variants: [lol], ...otherStuff })
545-
546520
let defaultOptions = {
547521
variants: [],
548522
respectPrefix: true,
@@ -558,7 +532,32 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
558532
let prefixedIdentifier = prefixIdentifier(identifier, options)
559533
let rule = utilities[identifier]
560534

561-
let withOffsets = [{ sort: offset, layer: 'utilities', options }, rule]
535+
function wrapped(modifier) {
536+
let { type = 'any' } = options
537+
let value = coerceValue(type, modifier, options.values)
538+
539+
if (value === undefined) {
540+
return []
541+
}
542+
543+
let includedRules = []
544+
let ruleSets = []
545+
.concat(
546+
rule(value, {
547+
includeRules(rules) {
548+
includedRules.push(...rules)
549+
},
550+
})
551+
)
552+
.filter(Boolean)
553+
.map((declaration) => ({
554+
[nameClass(identifier, modifier)]: declaration,
555+
}))
556+
557+
return [...includedRules, ...ruleSets]
558+
}
559+
560+
let withOffsets = [{ sort: offset, layer: 'utilities', options }, wrapped]
562561

563562
if (!context.candidateRuleMap.has(prefixedIdentifier)) {
564563
context.candidateRuleMap.set(prefixedIdentifier, [])
@@ -567,16 +566,6 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
567566
context.candidateRuleMap.get(prefixedIdentifier).push(withOffsets)
568567
}
569568
},
570-
// ---
571-
jit: {
572-
e: escapeClassName,
573-
config: tailwindConfig,
574-
theme: tailwindConfig.theme,
575-
addVariant(variantName, applyVariant, options = {}) {
576-
insertInto(variantList, variantName, options)
577-
variantMap.set(variantName, applyVariant)
578-
},
579-
},
580569
}
581570
}
582571

src/plugins/animation.js

+30-49
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,41 @@
1-
import _ from 'lodash'
21
import parseAnimationValue from '../util/parseAnimationValue'
3-
import nameClass from '../util/nameClass'
42

53
export default function () {
6-
return function ({ config, matchUtilities, addUtilities, theme, variants, prefix }) {
7-
if (config('mode') === 'jit') {
8-
let keyframes = Object.fromEntries(
9-
Object.entries(theme('keyframes')).map(([key, value]) => {
10-
return [
11-
key,
12-
[
13-
{
14-
[`@keyframes ${key}`]: value,
15-
},
16-
{ respectVariants: false },
17-
],
18-
]
19-
})
20-
)
4+
return function ({ matchUtilities, theme, variants, prefix }) {
5+
let prefixName = (name) => prefix(`.${name}`).slice(1)
6+
let keyframes = Object.fromEntries(
7+
Object.entries(theme('keyframes')).map(([key, value]) => {
8+
return [
9+
key,
10+
[
11+
{
12+
[`@keyframes ${prefixName(key)}`]: value,
13+
},
14+
{ respectVariants: false },
15+
],
16+
]
17+
})
18+
)
2119

22-
matchUtilities({
23-
animate: (modifier, { theme }) => {
24-
let value = theme.animation[modifier]
20+
matchUtilities(
21+
{
22+
animate: (value, { includeRules }) => {
23+
let { name: animationName } = parseAnimationValue(value)
2524

26-
if (value === undefined) {
27-
return []
25+
if (keyframes[animationName] !== undefined) {
26+
includeRules(keyframes[animationName], { respectImportant: false })
2827
}
2928

30-
let { name: animationName } = parseAnimationValue(value)
29+
if (animationName === undefined || keyframes[animationName] === undefined) {
30+
return { animation: value }
31+
}
3132

32-
return [
33-
keyframes[animationName],
34-
{ [nameClass('animate', modifier)]: { animation: value } },
35-
].filter(Boolean)
33+
return {
34+
animation: value.replace(animationName, prefixName(animationName)),
35+
}
3636
},
37-
})
38-
} else {
39-
const prefixName = (name) => prefix(`.${name}`).slice(1)
40-
const keyframesConfig = theme('keyframes')
41-
const keyframesStyles = _.mapKeys(
42-
keyframesConfig,
43-
(_keyframes, name) => `@keyframes ${prefixName(name)}`
44-
)
45-
46-
addUtilities(keyframesStyles, { respectImportant: false })
47-
48-
const animationConfig = theme('animation')
49-
const utilities = _.mapValues(
50-
_.mapKeys(animationConfig, (_animation, suffix) => nameClass('animate', suffix)),
51-
(animation) => {
52-
const { name } = parseAnimationValue(animation)
53-
if (name === undefined || keyframesConfig[name] === undefined) return { animation }
54-
return { animation: animation.replace(name, prefixName(name)) }
55-
}
56-
)
57-
addUtilities(utilities, variants('animation'))
58-
}
37+
},
38+
{ values: theme('animation'), variants: variants('animation') }
39+
)
5940
}
6041
}

src/plugins/backdropBlur.js

+12-34
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,16 @@
1-
import _ from 'lodash'
2-
import nameClass from '../util/nameClass'
3-
import { asValue } from '../util/pluginUtils'
4-
51
export default function () {
6-
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
7-
if (config('mode') === 'jit') {
8-
matchUtilities({
9-
'backdrop-blur': (modifier, { theme }) => {
10-
let value = asValue(modifier, theme.backdropBlur)
11-
12-
if (value === undefined) {
13-
return []
14-
}
15-
16-
return {
17-
[nameClass('backdrop-blur', modifier)]: { '--tw-backdrop-blur': `blur(${value})` },
18-
}
2+
return function ({ matchUtilities, theme, variants }) {
3+
matchUtilities(
4+
{
5+
'backdrop-blur': (value) => {
6+
return { '--tw-backdrop-blur': `blur(${value})` }
197
},
20-
})
21-
} else {
22-
const utilities = _.fromPairs(
23-
_.map(theme('backdropBlur'), (value, modifier) => {
24-
return [
25-
nameClass('backdrop-blur', modifier),
26-
{
27-
'--tw-backdrop-blur': Array.isArray(value)
28-
? value.map((v) => `blur(${v})`).join(' ')
29-
: `blur(${value})`,
30-
},
31-
]
32-
})
33-
)
34-
35-
addUtilities(utilities, variants('backdopBlur'))
36-
}
8+
},
9+
{
10+
values: theme('backdropBlur'),
11+
variants: variants('backdropBlur'),
12+
type: 'any',
13+
}
14+
)
3715
}
3816
}

src/plugins/backdropBrightness.js

+12-34
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,18 @@
1-
import _ from 'lodash'
2-
import nameClass from '../util/nameClass'
3-
import { asValue } from '../util/pluginUtils'
4-
51
export default function () {
6-
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
7-
if (config('mode') === 'jit') {
8-
matchUtilities({
9-
'backdrop-brightness': (modifier, { theme }) => {
10-
let value = asValue(modifier, theme.backdropBrightness)
11-
12-
if (value === undefined) {
13-
return []
14-
}
15-
2+
return function ({ matchUtilities, theme, variants }) {
3+
matchUtilities(
4+
{
5+
'backdrop-brightness': (value) => {
166
return {
17-
[nameClass('backdrop-brightness', modifier)]: {
18-
'--tw-backdrop-brightness': `brightness(${value})`,
19-
},
7+
'--tw-backdrop-brightness': `brightness(${value})`,
208
}
219
},
22-
})
23-
} else {
24-
const utilities = _.fromPairs(
25-
_.map(theme('backdropBrightness'), (value, modifier) => {
26-
return [
27-
nameClass('backdrop-brightness', modifier),
28-
{
29-
'--tw-backdrop-brightness': Array.isArray(value)
30-
? value.map((v) => `brightness(${v})`).join(' ')
31-
: `brightness(${value})`,
32-
},
33-
]
34-
})
35-
)
36-
37-
addUtilities(utilities, variants('backdropBrightness'))
38-
}
10+
},
11+
{
12+
values: theme('backdropBrightness'),
13+
variants: variants('backdropBrightness'),
14+
type: 'any',
15+
}
16+
)
3917
}
4018
}

src/plugins/backdropContrast.js

+12-36
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,16 @@
1-
import _ from 'lodash'
2-
import nameClass from '../util/nameClass'
3-
import { asValue } from '../util/pluginUtils'
4-
51
export default function () {
6-
return function ({ config, matchUtilities, addUtilities, theme, variants }) {
7-
if (config('mode') === 'jit') {
8-
matchUtilities({
9-
'backdrop-contrast': (modifier, { theme }) => {
10-
let value = asValue(modifier, theme.backdropContrast)
11-
12-
if (value === undefined) {
13-
return []
14-
}
15-
16-
return {
17-
[nameClass('backdrop-contrast', modifier)]: {
18-
'--tw-backdrop-contrast': `contrast(${value})`,
19-
},
20-
}
2+
return function ({ matchUtilities, theme, variants }) {
3+
matchUtilities(
4+
{
5+
'backdrop-contrast': (value) => {
6+
return { '--tw-backdrop-contrast': `contrast(${value})` }
217
},
22-
})
23-
} else {
24-
const utilities = _.fromPairs(
25-
_.map(theme('backdropContrast'), (value, modifier) => {
26-
return [
27-
nameClass('backdrop-contrast', modifier),
28-
{
29-
'--tw-backdrop-contrast': Array.isArray(value)
30-
? value.map((v) => `contrast(${v})`).join(' ')
31-
: `contrast(${value})`,
32-
},
33-
]
34-
})
35-
)
36-
37-
addUtilities(utilities, variants('backdropContrast'))
38-
}
8+
},
9+
{
10+
values: theme('backdropContrast'),
11+
variants: variants('backdropContrast'),
12+
type: 'any',
13+
}
14+
)
3915
}
4016
}

0 commit comments

Comments
 (0)