From 8646c94dd5fd2073b97d228f7c42458f133eb939 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Thu, 13 Aug 2020 20:16:56 -0400 Subject: [PATCH] Prepend a shadow lookup table when no @tailwind rules are in the tree --- __tests__/applyAtRule.test.js | 6 +++++- __tests__/applyComplexClasses.test.js | 11 +++++++++++ src/flagged/applyComplexClasses.js | 24 +++++++++++++++--------- src/lib/substituteTailwindAtRules.js | 9 +++------ src/processTailwindFeatures.js | 3 +++ 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/__tests__/applyAtRule.test.js b/__tests__/applyAtRule.test.js index 2de552e82..18db716a8 100644 --- a/__tests__/applyAtRule.test.js +++ b/__tests__/applyAtRule.test.js @@ -13,7 +13,11 @@ const { utilities: defaultUtilities } = processPlugins( ) function run(input, config = resolvedDefaultConfig, utilities = defaultUtilities) { - return postcss([substituteClassApplyAtRules(config, utilities)]).process(input, { + return postcss([ + substituteClassApplyAtRules(config, () => ({ + utilities, + })), + ]).process(input, { from: undefined, }) } diff --git a/__tests__/applyComplexClasses.test.js b/__tests__/applyComplexClasses.test.js index e8ebf2f4d..189c2c541 100644 --- a/__tests__/applyComplexClasses.test.js +++ b/__tests__/applyComplexClasses.test.js @@ -259,6 +259,17 @@ test('you can apply utility classes that do not actually exist as long as they w }) }) +test('the shadow lookup is only used if no @tailwind rules were in the source tree', () => { + const input = ` + @tailwind base; + .foo { @apply mt-4; } + ` + + return run(input).catch(e => { + expect(e).toMatchObject({ name: 'CssSyntaxError' }) + }) +}) + test.skip('you can apply utility classes without using the given prefix', () => { const input = ` .foo { @apply .tw-mt-4 .mb-4; } diff --git a/src/flagged/applyComplexClasses.js b/src/flagged/applyComplexClasses.js index 37dd7bbb9..a933b0d41 100644 --- a/src/flagged/applyComplexClasses.js +++ b/src/flagged/applyComplexClasses.js @@ -8,16 +8,17 @@ import substituteResponsiveAtRules from '../lib/substituteResponsiveAtRules' import convertLayerAtRulesToControlComments from '../lib/convertLayerAtRulesToControlComments' import substituteScreenAtRules from '../lib/substituteScreenAtRules' -function hasInject(css) { - let foundInject = false +function hasAtRule(css, atRule) { + let foundAtRule = false - css.walkAtRules('apply', () => { - foundInject = true + css.walkAtRules(atRule, () => { + foundAtRule = true return false }) - return foundInject + return foundAtRule } + function applyUtility(rule, className, replaceWith) { const processedSelectors = rule.selectors.map(selector => { const processor = selectorParser(selectors => { @@ -85,7 +86,7 @@ function buildUtilityMap(css) { index, utilityName, rule: rule.clone({ parent: rule.parent }), - containsApply: hasInject(rule), + containsApply: hasAtRule(rule, 'apply'), }) index++ }) @@ -153,10 +154,10 @@ function makeExtractUtilityRules(css) { } } -function themagic(css, lookupTree) { +function processApplyAtRules(css, lookupTree) { const extractUtilityRules = makeExtractUtilityRules(lookupTree) - while (hasInject(css)) { + while (hasAtRule(css, 'apply')) { css.walkRules(rule => { const injectRules = [] @@ -222,6 +223,11 @@ function themagic(css, lookupTree) { export default function applyComplexClasses(config, getProcessedPlugins) { return function(css) { + // Tree already contains @tailwind rules, don't prepend default Tailwind tree + if (hasAtRule(css, 'tailwind')) { + return processApplyAtRules(css, css) + } + return postcss([ substituteTailwindAtRules(config, getProcessedPlugins()), evaluateTailwindFunctions(config), @@ -242,7 +248,7 @@ export default function applyComplexClasses(config, getProcessedPlugins) { // if css already contains tailwind, css is the lookup tree const lookupTree = _.tap(css.clone(), tree => tree.prepend(result.root)) - return themagic(css, lookupTree) + return processApplyAtRules(css, lookupTree) }) } } diff --git a/src/lib/substituteTailwindAtRules.js b/src/lib/substituteTailwindAtRules.js index 4354d2847..ef9d36bf6 100644 --- a/src/lib/substituteTailwindAtRules.js +++ b/src/lib/substituteTailwindAtRules.js @@ -49,18 +49,15 @@ export default function( } if (atRule.params === 'base') { - atRule.before(updateSource(pluginBase, atRule.source)) - atRule.remove() + atRule.after(updateSource(pluginBase, atRule.source)) } if (atRule.params === 'components') { - atRule.before(updateSource(pluginComponents, atRule.source)) - atRule.remove() + atRule.after(updateSource(pluginComponents, atRule.source)) } if (atRule.params === 'utilities') { - atRule.before(updateSource(pluginUtilities, atRule.source)) - atRule.remove() + atRule.after(updateSource(pluginUtilities, atRule.source)) } if (atRule.params === 'screens') { diff --git a/src/processTailwindFeatures.js b/src/processTailwindFeatures.js index 729e3ff9c..7ea80ee8f 100644 --- a/src/processTailwindFeatures.js +++ b/src/processTailwindFeatures.js @@ -40,6 +40,9 @@ export default function(getConfig) { convertLayerAtRulesToControlComments(config), substituteScreenAtRules(config), substituteClassApplyAtRules(config, getProcessedPlugins), + function(css) { + css.walkAtRules('tailwind', rule => rule.remove()) + }, purgeUnusedStyles(config), ]).process(css, { from: _.get(css, 'source.input.file') }) }