diff --git a/CHANGELOG.md b/CHANGELOG.md index d0cb726bfac4..e83454031851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Cleanup duplicate properties ([#5830](https://github.com/tailwindlabs/tailwindcss/pull/5830)) - Allow `_` inside `url()` when using arbitrary values ([#5853](https://github.com/tailwindlabs/tailwindcss/pull/5853)) - Prevent crashes when using comments in `@layer` AtRules ([#5854](https://github.com/tailwindlabs/tailwindcss/pull/5854)) +- Handle color transformations properly with `theme(...)` for all relevant plugins ([#4533](https://github.com/tailwindlabs/tailwindcss/pull/4533), [#5871](https://github.com/tailwindlabs/tailwindcss/pull/5871)) ## [3.0.0-alpha.1] - 2021-10-01 diff --git a/src/util/transformThemeValue.js b/src/util/transformThemeValue.js index dbd7a3e2e80b..e6a8b8735317 100644 --- a/src/util/transformThemeValue.js +++ b/src/util/transformThemeValue.js @@ -2,7 +2,12 @@ import postcss from 'postcss' export default function transformThemeValue(themeSection) { if (['fontSize', 'outline'].includes(themeSection)) { - return (value) => (Array.isArray(value) ? value[0] : value) + return (value) => { + if (typeof value === 'function') value = value({}) + if (Array.isArray(value)) value = value[0] + + return value + } } if ( @@ -20,18 +25,28 @@ export default function transformThemeValue(themeSection) { 'animation', ].includes(themeSection) ) { - return (value) => (Array.isArray(value) ? value.join(', ') : value) + return (value) => { + if (typeof value === 'function') value = value({}) + if (Array.isArray(value)) value = value.join(', ') + + return value + } } // For backwards compatibility reasons, before we switched to underscores // instead of commas for arbitrary values. if (['gridTemplateColumns', 'gridTemplateRows', 'objectPosition'].includes(themeSection)) { - return (value) => (typeof value === 'string' ? postcss.list.comma(value).join(' ') : value) - } + return (value) => { + if (typeof value === 'function') value = value({}) + if (typeof value === 'string') value = postcss.list.comma(value).join(' ') - if (themeSection === 'colors') { - return (value) => (typeof value === 'function' ? value({}) : value) + return value + } } - return (value) => value + return (value) => { + if (typeof value === 'function') value = value({}) + + return value + } } diff --git a/tests/evaluateTailwindFunctions.test.js b/tests/evaluateTailwindFunctions.test.js index 416ceaac8481..b2c69a0a144b 100644 --- a/tests/evaluateTailwindFunctions.test.js +++ b/tests/evaluateTailwindFunctions.test.js @@ -26,6 +26,60 @@ test('it looks up values in the theme using dot notation', () => { }) }) +test('color can be a function', () => { + const input = ` + .backgroundColor { color: theme('backgroundColor.fn') } + .borderColor { color: theme('borderColor.fn') } + .caretColor { color: theme('caretColor.fn') } + .colors { color: theme('colors.fn') } + .divideColor { color: theme('divideColor.fn') } + .fill { color: theme('fill.fn') } + .gradientColorStops { color: theme('gradientColorStops.fn') } + .placeholderColor { color: theme('placeholderColor.fn') } + .ringColor { color: theme('ringColor.fn') } + .ringOffsetColor { color: theme('ringOffsetColor.fn') } + .stroke { color: theme('stroke.fn') } + .textColor { color: theme('textColor.fn') } + ` + + const output = ` + .backgroundColor { color: #f00 } + .borderColor { color: #f00 } + .caretColor { color: #f00 } + .colors { color: #f00 } + .divideColor { color: #f00 } + .fill { color: #f00 } + .gradientColorStops { color: #f00 } + .placeholderColor { color: #f00 } + .ringColor { color: #f00 } + .ringOffsetColor { color: #f00 } + .stroke { color: #f00 } + .textColor { color: #f00 } + ` + + const fn = () => `#f00` + + return run(input, { + theme: { + backgroundColor: { fn }, + borderColor: { fn }, + caretColor: { fn }, + colors: { fn }, + divideColor: { fn }, + fill: { fn }, + gradientColorStops: { fn }, + placeholderColor: { fn }, + ringColor: { fn }, + ringOffsetColor: { fn }, + stroke: { fn }, + textColor: { fn }, + }, + }).then((result) => { + expect(result.css).toEqual(output) + expect(result.warnings().length).toBe(0) + }) +}) + test('quotes are optional around the lookup path', () => { const input = ` .banana { color: theme(colors.yellow); }