From e130771c320b013e061a8fc6e55c32daf10ebb10 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Fri, 11 Oct 2019 13:39:05 -0400 Subject: [PATCH] Allow plugins to modify the config --- __tests__/modifyConfig.test.js | 58 ++++++++++++++++++++++++++++++++ __tests__/processPlugins.test.js | 40 +++++++++++++++++++++- src/index.js | 13 ++++--- src/util/processPlugins.js | 5 ++- 4 files changed, 110 insertions(+), 6 deletions(-) create mode 100644 __tests__/modifyConfig.test.js diff --git a/__tests__/modifyConfig.test.js b/__tests__/modifyConfig.test.js new file mode 100644 index 000000000..618838c5a --- /dev/null +++ b/__tests__/modifyConfig.test.js @@ -0,0 +1,58 @@ +import postcss from 'postcss' +import tailwind from '../src/index' + +test('plugins can add new theme values', () => { + return postcss([ + tailwind({ + corePlugins: [], + plugins: [ + { + modifyConfig: function(config) { + return { + ...config, + theme: { + ...config.theme, + rotate: { + '0': '0deg', + '90': '90deg', + '180': '180deg', + '270': '270deg', + } + } + } + }, + handler: function({ addUtilities, theme }) { + addUtilities(Object.entries(theme('rotate')).map(([key, value]) => { + return { + [`.rotate-${key}`]: { + transform: `rotate(${value})`, + }, + } + })) + }, + } + ] + }), + ]) + .process('@tailwind utilities;', + { from: undefined } + ) + .then(result => { + const expected = ` + .rotate-0 { + transform: rotate(0deg) + } + .rotate-90 { + transform: rotate(90deg) + } + .rotate-180 { + transform: rotate(180deg) + } + .rotate-270 { + transform: rotate(270deg) + } + ` + + expect(result.css).toMatchCss(expected) + }) +}) diff --git a/__tests__/processPlugins.test.js b/__tests__/processPlugins.test.js index 58e8b85e0..2c323ed6c 100644 --- a/__tests__/processPlugins.test.js +++ b/__tests__/processPlugins.test.js @@ -47,7 +47,7 @@ test('plugins can create utilities with object syntax', () => { object-fit: cover } } - `) + `) }) test('plugins can create utilities with arrays of objects', () => { @@ -1206,3 +1206,41 @@ test('prefix will prefix all classes in a selector', () => { } `) }) + +test('plugins can be provided as an object with a handler function', () => { + const { components, utilities } = processPlugins( + [ + { + handler: function({ addUtilities }) { + addUtilities({ + '.object-fill': { + 'object-fit': 'fill', + }, + '.object-contain': { + 'object-fit': 'contain', + }, + '.object-cover': { + 'object-fit': 'cover', + }, + }) + }, + } + ], + makeConfig() + ) + + expect(components.length).toBe(0) + expect(css(utilities)).toMatchCss(` + @variants { + .object-fill { + object-fit: fill + } + .object-contain { + object-fit: contain + } + .object-cover { + object-fit: cover + } + } + `) +}) diff --git a/src/index.js b/src/index.js index b86050c2e..32225d99f 100644 --- a/src/index.js +++ b/src/index.js @@ -44,6 +44,12 @@ function resolveConfigPath(filePath) { } } +function applyPluginConfigModifications(config) { + return [...config.plugins].reduce((modified, plugin) => { + return _.get(plugin, 'modifyConfig', _.identity)(modified) + }, config) +} + const getConfigFunction = config => () => { if (_.isUndefined(config) && !_.isObject(config)) { return resolveConfig([defaultConfig]) @@ -55,10 +61,9 @@ const getConfigFunction = config => () => { }) } - return resolveConfig([ - _.isObject(config) ? _.get(config, 'config', config) : require(config), - defaultConfig, - ]) + const configObject = _.isObject(config) ? _.get(config, 'config', config) : require(config) + + return resolveConfig([applyPluginConfigModifications(configObject), defaultConfig]) } const plugin = postcss.plugin('tailwind', config => { diff --git a/src/util/processPlugins.js b/src/util/processPlugins.js index c59af2918..3618238cc 100644 --- a/src/util/processPlugins.js +++ b/src/util/processPlugins.js @@ -1,6 +1,7 @@ import _ from 'lodash' import postcss from 'postcss' import Node from 'postcss/lib/node' +import isFunction from 'lodash/isFunction' import escapeClassName from '../util/escapeClassName' import generateVariantFunction from '../util/generateVariantFunction' import parseObjectStyles from '../util/parseObjectStyles' @@ -28,7 +29,9 @@ export default function(plugins, config) { const getConfigValue = (path, defaultValue) => _.get(config, path, defaultValue) plugins.forEach(plugin => { - plugin({ + const handler = isFunction(plugin) ? plugin : plugin.handler + + handler({ postcss, config: getConfigValue, theme: (path, defaultValue) => getConfigValue(`theme.${path}`, defaultValue),