From 600523daf20429398f04e7a19e165c89751c19d8 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Wed, 30 Sep 2020 12:51:40 -0400 Subject: [PATCH] Support array for Tailwind config --- __tests__/customConfig.test.js | 87 +++++++++++++++++++++++++++++++++ __tests__/resolveConfig.test.js | 11 +++-- jest/runInTempDirectory.js | 4 +- resolveConfig.js | 4 +- src/index.js | 10 +++- src/processTailwindFeatures.js | 2 +- src/util/prefixSelector.js | 3 +- src/util/processPlugins.js | 2 +- src/util/resolveConfig.js | 3 ++ 9 files changed, 117 insertions(+), 9 deletions(-) diff --git a/__tests__/customConfig.test.js b/__tests__/customConfig.test.js index 5c3f3e7d2404..c8be6bd0ee70 100644 --- a/__tests__/customConfig.test.js +++ b/__tests__/customConfig.test.js @@ -210,3 +210,90 @@ test('tailwind.config.js is picked up by default when passing an empty object', }) }) }) + +test('when custom config is an array the default config is not included', () => { + return postcss([ + tailwind([ + { + theme: { + extend: { + colors: { + black: 'black', + }, + backgroundColor: theme => theme('colors'), + }, + }, + corePlugins: ['backgroundColor'], + }, + { + theme: { + extend: { colors: { white: 'white' } }, + }, + }, + ]), + ]) + .process( + ` + @tailwind utilities + `, + { from: undefined } + ) + .then(result => { + const expected = ` + .bg-black { + background-color: black; + } + .bg-white { + background-color: white; + } + ` + + expect(result.css).toMatchCss(expected) + }) +}) + +test('when custom config is an array in a file the default config is not included', () => { + return inTempDirectory(() => { + fs.writeFileSync( + path.resolve(defaultConfigFile), + `module.exports = [ + { + theme: { + extend: { + colors: { + black: 'black', + }, + backgroundColor: theme => theme('colors'), + }, + }, + corePlugins: ['backgroundColor'], + }, + { + theme: { + extend: { colors: { white: 'white' } }, + }, + } + ]` + ) + + return postcss([tailwind()]) + .process( + ` + @tailwind utilities + `, + { from: undefined } + ) + .then(result => { + const expected = ` + .bg-black { + background-color: black; + } + .bg-white { + background-color: white; + } + ` + + expect(result.css).toMatchCss(expected) + }) + }) +}) diff --git a/__tests__/resolveConfig.test.js b/__tests__/resolveConfig.test.js index c4e27d091411..f2db50ea55c5 100644 --- a/__tests__/resolveConfig.test.js +++ b/__tests__/resolveConfig.test.js @@ -1796,7 +1796,6 @@ test('variants can be defined as a function', () => { rotate: ['responsive', 'focus'], cursor: ['focus', 'checked', 'hover'], }, - plugins: userConfig.plugins, }) }) @@ -1831,6 +1830,12 @@ test('core plugin configurations stack', () => { corePlugins: { display: false }, } + const otherConfig = { + corePlugins: ({ corePlugins }) => { + return [...corePlugins, 'margin'] + }, + } + const defaultConfig = { prefix: '', important: false, @@ -1840,7 +1845,7 @@ test('core plugin configurations stack', () => { corePlugins: ['float', 'display', 'padding'], } - const result = resolveConfig([userConfig, defaultConfig]) + const result = resolveConfig([userConfig, otherConfig, defaultConfig]) expect(result).toMatchObject({ prefix: '', @@ -1848,6 +1853,6 @@ test('core plugin configurations stack', () => { separator: ':', theme: {}, variants: {}, - corePlugins: ['float', 'padding'], + corePlugins: ['float', 'padding', 'margin'], }) }) diff --git a/jest/runInTempDirectory.js b/jest/runInTempDirectory.js index 025361045d58..c0928e219141 100644 --- a/jest/runInTempDirectory.js +++ b/jest/runInTempDirectory.js @@ -3,9 +3,11 @@ import path from 'path' import rimraf from 'rimraf' +let id = 0 + export default function(callback) { return new Promise(resolve => { - const workerId = process.env.JEST_WORKER_ID + const workerId = `${process.env.JEST_WORKER_ID}-${id++}` const tmpPath = path.resolve(__dirname, `../__tmp_${workerId}`) const currentPath = process.cwd() diff --git a/resolveConfig.js b/resolveConfig.js index a9db71f4641e..5a65b6f73616 100644 --- a/resolveConfig.js +++ b/resolveConfig.js @@ -2,7 +2,9 @@ const resolveConfigObjects = require('./lib/util/resolveConfig').default const getAllConfigs = require('./lib/util/getAllConfigs').default module.exports = function resolveConfig(...configs) { + if (configs.length === 1 && Array.isArray(configs[0])) { + return resolveConfigObjects([...configs[0]].reverse()) + } const [, ...defaultConfigs] = getAllConfigs(configs[0]) - return resolveConfigObjects([...configs, ...defaultConfigs]) } diff --git a/src/index.js b/src/index.js index 4b34ee27bc02..ae4f06b5b46b 100644 --- a/src/index.js +++ b/src/index.js @@ -14,6 +14,10 @@ import { defaultConfigFile } from './constants' import defaultConfig from '../stubs/defaultConfig.stub.js' function resolveConfigPath(filePath) { + // require('tailwindcss')([{ theme: ..., variants: ... }, {...}]) + if (Array.isArray(filePath)) { + return undefined + } // require('tailwindcss')({ theme: ..., variants: ... }) if (_.isObject(filePath) && !_.has(filePath, 'config') && !_.isEmpty(filePath)) { return undefined @@ -45,7 +49,7 @@ function resolveConfigPath(filePath) { } const getConfigFunction = config => () => { - if (_.isUndefined(config) && !_.isObject(config)) { + if (_.isUndefined(config)) { return resolveConfig([...getAllConfigs(defaultConfig)]) } @@ -60,6 +64,10 @@ const getConfigFunction = config => () => { const configObject = _.isObject(config) ? _.get(config, 'config', config) : require(config) + if (Array.isArray(configObject)) { + return resolveConfig([...configObject].reverse()) + } + return resolveConfig([...getAllConfigs(configObject)]) } diff --git a/src/processTailwindFeatures.js b/src/processTailwindFeatures.js index a93ad611db0a..4d94b47da835 100644 --- a/src/processTailwindFeatures.js +++ b/src/processTailwindFeatures.js @@ -37,7 +37,7 @@ export default function(getConfig) { [ ...corePlugins(config), ...[flagEnabled(config, 'darkModeVariant') ? darkModeVariantPlugin : () => {}], - ...config.plugins, + ..._.get(config, 'plugins', []), ], config ) diff --git a/src/util/prefixSelector.js b/src/util/prefixSelector.js index c4448e8af906..7f9c9a95d09f 100644 --- a/src/util/prefixSelector.js +++ b/src/util/prefixSelector.js @@ -2,7 +2,8 @@ import parser from 'postcss-selector-parser' import tap from 'lodash/tap' export default function(prefix, selector) { - const getPrefix = typeof prefix === 'function' ? prefix : () => prefix + const getPrefix = + typeof prefix === 'function' ? prefix : () => (prefix === undefined ? '' : prefix) return parser(selectors => { selectors.walkClasses(classSelector => { diff --git a/src/util/processPlugins.js b/src/util/processPlugins.js index d381e4c931cf..1b33d5f343e5 100644 --- a/src/util/processPlugins.js +++ b/src/util/processPlugins.js @@ -74,7 +74,7 @@ export default function(plugins, config) { return config.target === 'browserslist' ? browserslistTarget : config.target } - const [defaultTarget, targetOverrides] = getConfigValue('target') + const [defaultTarget, targetOverrides] = getConfigValue('target', 'relaxed') const target = _.get(targetOverrides, path, defaultTarget) diff --git a/src/util/resolveConfig.js b/src/util/resolveConfig.js index 31b738e45489..961cc93a1037 100644 --- a/src/util/resolveConfig.js +++ b/src/util/resolveConfig.js @@ -191,6 +191,9 @@ function resolveVariants([firstConfig, ...variantConfigs]) { function resolveCorePlugins(corePluginConfigs) { const result = [...corePluginConfigs].reverse().reduce((resolved, corePluginConfig) => { + if (isFunction(corePluginConfig)) { + return corePluginConfig({ corePlugins: resolved }) + } return configurePlugins(corePluginConfig, resolved) }, Object.keys(corePluginList))