From 722232cb2ed49f323ba34b75970163c87fa63a88 Mon Sep 17 00:00:00 2001 From: Gary Mathews Date: Tue, 4 Jan 2022 05:23:10 -0800 Subject: [PATCH] Allow all classes for @apply (#6580) * Always include css with apply in context * Use let We use it more consistently * Remove early return To match the style of the surrounding code * Don't return layer directives They do not need to be returned here. If it's needed in the future its easy enough to add it back. * Use let * Update changelog * fix typo And re-format comments Co-authored-by: Jordan Pittman Co-authored-by: Robin Malfait --- CHANGELOG.md | 4 ++- src/lib/normalizeTailwindDirectives.js | 7 +++++- src/lib/setupTrackingContext.js | 21 ++++++++-------- src/processTailwindFeatures.js | 3 ++- tests/apply.test.js | 35 ++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1206d79a..61e89a11d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +### Fixed + +- Fix `@apply` in files without `@tailwind` directives ([#6580](https://github.com/tailwindlabs/tailwindcss/pull/6580)) ## [3.0.9] - 2022-01-03 diff --git a/src/lib/normalizeTailwindDirectives.js b/src/lib/normalizeTailwindDirectives.js index 274773051..a60d217e2 100644 --- a/src/lib/normalizeTailwindDirectives.js +++ b/src/lib/normalizeTailwindDirectives.js @@ -3,8 +3,13 @@ import log from '../util/log' export default function normalizeTailwindDirectives(root) { let tailwindDirectives = new Set() let layerDirectives = new Set() + let applyDirectives = new Set() root.walkAtRules((atRule) => { + if (atRule.name === 'apply') { + applyDirectives.add(atRule) + } + if (atRule.name === 'import') { if (atRule.params === '"tailwindcss/base"' || atRule.params === "'tailwindcss/base'") { atRule.name = 'tailwind' @@ -74,5 +79,5 @@ export default function normalizeTailwindDirectives(root) { } } - return tailwindDirectives + return { tailwindDirectives, applyDirectives } } diff --git a/src/lib/setupTrackingContext.js b/src/lib/setupTrackingContext.js index d4015c5bf..49050fd3b 100644 --- a/src/lib/setupTrackingContext.js +++ b/src/lib/setupTrackingContext.js @@ -112,19 +112,20 @@ function resolveChangedFiles(candidateFiles, fileModifiedMap) { // source path), or set up a new one (including setting up watchers and registering // plugins) then return it export default function setupTrackingContext(configOrPath) { - return ({ tailwindDirectives, registerDependency }) => { + return ({ tailwindDirectives, registerDependency, applyDirectives }) => { return (root, result) => { let [tailwindConfig, userConfigPath, tailwindConfigHash, configDependencies] = getTailwindConfig(configOrPath) let contextDependencies = new Set(configDependencies) - // If there are no @tailwind rules, we don't consider this CSS file or it's dependencies - // to be dependencies of the context. Can reuse the context even if they change. - // We may want to think about `@layer` being part of this trigger too, but it's tough - // because it's impossible for a layer in one file to end up in the actual @tailwind rule - // in another file since independent sources are effectively isolated. - if (tailwindDirectives.size > 0) { + // If there are no @tailwind or @apply rules, we don't consider this CSS + // file or its dependencies to be dependencies of the context. Can reuse + // the context even if they change. We may want to think about `@layer` + // being part of this trigger too, but it's tough because it's impossible + // for a layer in one file to end up in the actual @tailwind rule in + // another file since independent sources are effectively isolated. + if (tailwindDirectives.size > 0 || applyDirectives.size > 0) { // Add current css file as a context dependencies. contextDependencies.add(result.opts.from) @@ -147,12 +148,12 @@ export default function setupTrackingContext(configOrPath) { let candidateFiles = getCandidateFiles(context, tailwindConfig) - // If there are no @tailwind rules, we don't consider this CSS file or it's dependencies - // to be dependencies of the context. Can reuse the context even if they change. + // If there are no @tailwind or @apply rules, we don't consider this CSS file or it's + // dependencies to be dependencies of the context. Can reuse the context even if they change. // We may want to think about `@layer` being part of this trigger too, but it's tough // because it's impossible for a layer in one file to end up in the actual @tailwind rule // in another file since independent sources are effectively isolated. - if (tailwindDirectives.size > 0) { + if (tailwindDirectives.size > 0 || applyDirectives.size > 0) { let fileModifiedMap = getFileModifiedMap(context) // Add template paths as postcss dependencies. diff --git a/src/processTailwindFeatures.js b/src/processTailwindFeatures.js index 8a6d22dae..7c622205b 100644 --- a/src/processTailwindFeatures.js +++ b/src/processTailwindFeatures.js @@ -12,10 +12,11 @@ import { issueFlagNotices } from './featureFlags' export default function processTailwindFeatures(setupContext) { return function (root, result) { - let tailwindDirectives = normalizeTailwindDirectives(root) + let { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root) let context = setupContext({ tailwindDirectives, + applyDirectives, registerDependency(dependency) { result.messages.push({ plugin: 'tailwindcss', diff --git a/tests/apply.test.js b/tests/apply.test.js index 59807a633..25ca0b24c 100644 --- a/tests/apply.test.js +++ b/tests/apply.test.js @@ -775,3 +775,38 @@ it('should not apply unrelated siblings when applying something from within atru `) }) }) + +it('should be possible to apply user css without tailwind directives', () => { + let config = { + content: [{ raw: html`
` }], + plugins: [], + } + + let input = css` + .bop { + color: red; + } + .bar { + background-color: blue; + } + .foo { + @apply absolute bar bop; + } + ` + + return run(input, config).then((result) => { + return expect(result.css).toMatchFormattedCss(css` + .bop { + color: red; + } + .bar { + background-color: blue; + } + .foo { + position: absolute; + color: red; + background-color: blue; + } + `) + }) +})