diff --git a/__tests__/resolveConfig.test.js b/__tests__/resolveConfig.test.js index a61923098..8aabd8a36 100644 --- a/__tests__/resolveConfig.test.js +++ b/__tests__/resolveConfig.test.js @@ -1359,15 +1359,13 @@ test('more than two config objects can be resolved', () => { }, }) }) + test('plugin config modifications are applied', () => { const userConfig = { plugins: [ { - modifyConfig(config) { - return { - ...config, - prefix: 'tw-', - } + config: { + prefix: 'tw-', }, handler() {}, }, @@ -1415,11 +1413,8 @@ test('user config takes precedence over plugin config modifications', () => { prefix: 'user-', plugins: [ { - modifyConfig(config) { - return { - ...config, - prefix: 'plugin-', - } + config: { + prefix: 'tw-', }, handler() {}, }, @@ -1461,3 +1456,121 @@ test('user config takes precedence over plugin config modifications', () => { plugins: userConfig.plugins, }) }) + +test('plugin config can register plugins that also have config', () => { + const userConfig = { + plugins: [ + { + config: { + prefix: 'tw-', + plugins: [ + { + config: { + important: true, + }, + handler() {} + }, + { + config: { + separator: '__', + }, + handler() {} + }, + ] + }, + handler() {}, + }, + ], + } + + const defaultConfig = { + prefix: '', + important: false, + separator: ':', + theme: { + screens: { + mobile: '400px', + }, + }, + variants: { + appearance: ['responsive'], + borderCollapse: [], + borderColors: ['responsive', 'hover', 'focus'], + }, + } + + const result = resolveConfig([userConfig, defaultConfig]) + + expect(result).toEqual({ + prefix: 'tw-', + important: true, + separator: '__', + theme: { + screens: { + mobile: '400px', + }, + }, + variants: { + appearance: ['responsive'], + borderCollapse: [], + borderColors: ['responsive', 'hover', 'focus'], + }, + plugins: userConfig.plugins, + }) +}) + +test('plugin configs take precedence over plugin configs registered by that plugin', () => { + const userConfig = { + plugins: [ + { + config: { + prefix: 'outer-', + plugins: [ + { + config: { + prefix: 'inner-', + }, + handler() {} + } + ] + }, + handler() {}, + }, + ], + } + + const defaultConfig = { + prefix: '', + important: false, + separator: ':', + theme: { + screens: { + mobile: '400px', + }, + }, + variants: { + appearance: ['responsive'], + borderCollapse: [], + borderColors: ['responsive', 'hover', 'focus'], + }, + } + + const result = resolveConfig([userConfig, defaultConfig]) + + expect(result).toEqual({ + prefix: 'outer-', + important: false, + separator: ':', + theme: { + screens: { + mobile: '400px', + }, + }, + variants: { + appearance: ['responsive'], + borderCollapse: [], + borderColors: ['responsive', 'hover', 'focus'], + }, + plugins: userConfig.plugins, + }) +}) diff --git a/src/index.js b/src/index.js index 9dd2ab582..e5db638ba 100644 --- a/src/index.js +++ b/src/index.js @@ -56,7 +56,7 @@ const getConfigFunction = config => () => { } const configObject = _.isObject(config) ? _.get(config, 'config', config) : require(config) - + return resolveConfig([configObject, defaultConfig]) } diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index 414b896bb..1ab7b4b66 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -1,10 +1,9 @@ import some from 'lodash/some' import mergeWith from 'lodash/mergeWith' +import isEmpty from 'lodash/isEmpty' import isFunction from 'lodash/isFunction' import isUndefined from 'lodash/isUndefined' import defaults from 'lodash/defaults' -import identity from 'lodash/identity' -import get from 'lodash/get' import map from 'lodash/map' import get from 'lodash/get' import toPath from 'lodash/toPath' @@ -24,12 +23,6 @@ const configUtils = { }, } -function applyPluginConfigModifications(config, plugins) { - return plugins.reduce((modified, plugin) => { - return get(plugin, 'modifyConfig', identity)(modified) - }, config) -} - function value(valueToResolve, ...args) { return isFunction(valueToResolve) ? valueToResolve(...args) : valueToResolve } @@ -102,25 +95,41 @@ function resolveFunctionKeys(object) { }, {}) } -export default function resolveConfig([userConfig, defaultConfig]) { - const modifiedDefaultConfig = applyPluginConfigModifications( - defaultConfig, - get(userConfig, 'plugins', []) - ) - const configs = [userConfig, modifiedDefaultConfig] +function extractPluginConfigs(configs) { + let allConfigs = [] + + configs.forEach(config => { + allConfigs = [...allConfigs, config] + + const plugins = get(config, 'plugins', []) + + if (plugins.length === 0) { + return + } + + plugins.forEach(plugin => { + allConfigs = [...allConfigs, ...extractPluginConfigs([get(plugin, 'config', {})])] + }) + }) + + return allConfigs +} + +export default function resolveConfig(configs) { + const allConfigs = extractPluginConfigs(configs) return defaults( { // Need to get a default empty object if the config has no theme theme: resolveFunctionKeys( - mergeExtensions(mergeThemes(map(configs, t => get(t, 'theme', {})))) + mergeExtensions(mergeThemes(map(allConfigs, t => get(t, 'theme', {})))) ), variants: (firstVariants => { return Array.isArray(firstVariants) ? firstVariants - : defaults({}, ...map(configs, 'variants')) - })(defaults({}, ...map(configs)).variants), + : defaults({}, ...map(allConfigs, 'variants')) + })(defaults({}, ...map(allConfigs)).variants), }, - ...configs + ...allConfigs ) }