diff --git a/CHANGELOG.md b/CHANGELOG.md index b1206d79aec3..61e89a11d00f 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 274773051680..a60d217e22a6 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 d4015c5bf59e..49050fd3bdca 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 8a6d22dae744..7c622205b623 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 59807a633129..25ca0b24cc5f 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; + } + `) + }) +})