From cd2db712c50886d43dcc3e1835f764ee93c8f30c Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Fri, 30 Apr 2021 11:21:43 -0400 Subject: [PATCH] Very basic AOT matchUtilities support --- src/util/processPlugins.js | 57 +++++++++++++++++------------ tests/processPlugins.test.js | 69 ++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 22 deletions(-) diff --git a/src/util/processPlugins.js b/src/util/processPlugins.js index b5c891255..cc2f9d33a 100644 --- a/src/util/processPlugins.js +++ b/src/util/processPlugins.js @@ -41,6 +41,33 @@ export default function (plugins, config) { return prefixSelector(config.prefix, selector) } + function addUtilities(utilities, options) { + const defaultOptions = { variants: [], respectPrefix: true, respectImportant: true } + + options = Array.isArray(options) + ? Object.assign({}, defaultOptions, { variants: options }) + : _.defaults(options, defaultOptions) + + const styles = postcss.root({ nodes: parseStyles(utilities) }) + + styles.walkRules((rule) => { + if (options.respectPrefix && !isKeyframeRule(rule)) { + rule.selector = applyConfiguredPrefix(rule.selector) + } + + if (options.respectImportant && config.important) { + rule.__tailwind = { + ...rule.__tailwind, + important: config.important, + } + } + }) + + pluginUtilities.push( + wrapWithLayer(wrapWithVariants(styles.nodes, options.variants), 'utilities') + ) + } + const getConfigValue = (path, defaultValue) => (path ? _.get(config, path, defaultValue) : config) plugins.forEach((plugin) => { @@ -75,31 +102,17 @@ export default function (plugins, config) { }, e: escapeClassName, prefix: applyConfiguredPrefix, - addUtilities: (utilities, options) => { - const defaultOptions = { variants: [], respectPrefix: true, respectImportant: true } + addUtilities, + matchUtilities: (matches, { values, variants, respectPrefix, respectImportant }) => { + let modifierValues = Object.entries(values) - options = Array.isArray(options) - ? Object.assign({}, defaultOptions, { variants: options }) - : _.defaults(options, defaultOptions) - - const styles = postcss.root({ nodes: parseStyles(utilities) }) - - styles.walkRules((rule) => { - if (options.respectPrefix && !isKeyframeRule(rule)) { - rule.selector = applyConfiguredPrefix(rule.selector) - } - - if (options.respectImportant && config.important) { - rule.__tailwind = { - ...rule.__tailwind, - important: config.important, - } - } + let result = Object.values(matches).flatMap((utilityFunction) => { + return modifierValues.map(([modifier, value]) => { + return utilityFunction(modifier, { value }) + }) }) - pluginUtilities.push( - wrapWithLayer(wrapWithVariants(styles.nodes, options.variants), 'utilities') - ) + addUtilities(result, { variants, respectPrefix, respectImportant }) }, addComponents: (components, options) => { const defaultOptions = { variants: [], respectPrefix: true } diff --git a/tests/processPlugins.test.js b/tests/processPlugins.test.js index eb762f72f..87f48d8d8 100644 --- a/tests/processPlugins.test.js +++ b/tests/processPlugins.test.js @@ -2483,3 +2483,72 @@ test('animation values are joined when retrieved using the theme function', () = } `) }) + +test('plugins can add utilities using matchUtilities in AOT mode', () => { + const { components, utilities } = processPlugins( + [ + function ({ matchUtilities, theme, variants }) { + matchUtilities( + { + 'flex-grow': (modifier, { value }) => { + return { + [`.flex-grow-${modifier}`]: { + 'flex-grow': value, + }, + } + }, + 'flex-shrink': (modifier, { value }) => { + return { + [`.flex-shrink-${modifier}`]: { + 'flex-shrink': value, + }, + } + }, + }, + { + values: theme('flexyPants'), + variants: variants('flexyPants'), + } + ) + }, + ], + makeConfig({ + theme: { + flexyPants: { + 0: '0', + 1: '1', + 2: '2', + }, + }, + variants: { + flexyPants: ['responsive', 'hover', 'focus'], + }, + }) + ) + + expect(components.length).toBe(0) + expect(css(utilities)).toMatchCss(` + @layer utilities { + @variants responsive, hover, focus { + .flex-grow-0 { + flex-grow: 0 + } + .flex-grow-1 { + flex-grow: 1 + } + .flex-grow-2 { + flex-grow: 2 + } + .flex-shrink-0 { + flex-shrink: 0 + } + .flex-shrink-1 { + flex-shrink: 1 + } + .flex-shrink-2 { + flex-shrink: 2 + } + } + } + `) +})