From 19c300018174948b3490204936aa0cbf6fd7c920 Mon Sep 17 00:00:00 2001 From: Gary Mathews Date: Sat, 18 Dec 2021 15:39:37 -0800 Subject: [PATCH 1/7] Always include css with apply in context --- src/lib/normalizeTailwindDirectives.js | 11 +++++--- src/lib/setupTrackingContext.js | 14 +++++------ src/lib/setupWatchingContext.js | 10 ++++---- src/processTailwindFeatures.js | 5 ++-- tests/apply.test.js | 35 ++++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 17 deletions(-) diff --git a/src/lib/normalizeTailwindDirectives.js b/src/lib/normalizeTailwindDirectives.js index 274773051680..4d09f96806f5 100644 --- a/src/lib/normalizeTailwindDirectives.js +++ b/src/lib/normalizeTailwindDirectives.js @@ -1,10 +1,15 @@ import log from '../util/log' export default function normalizeTailwindDirectives(root) { - let tailwindDirectives = new Set() - let layerDirectives = new Set() + const tailwindDirectives = new Set() + const layerDirectives = new Set() + const applyDirectives = new Set() root.walkAtRules((atRule) => { + if (atRule.name === 'apply') { + applyDirectives.add(atRule) + return + } 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, layerDirectives, applyDirectives } } diff --git a/src/lib/setupTrackingContext.js b/src/lib/setupTrackingContext.js index d4015c5bf59e..4cf7b3cc48c1 100644 --- a/src/lib/setupTrackingContext.js +++ b/src/lib/setupTrackingContext.js @@ -112,19 +112,19 @@ 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. + // 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) { // Add current css file as a context dependencies. contextDependencies.add(result.opts.from) @@ -147,12 +147,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/lib/setupWatchingContext.js b/src/lib/setupWatchingContext.js index 1ee1eaf3094e..1787c4243561 100644 --- a/src/lib/setupWatchingContext.js +++ b/src/lib/setupWatchingContext.js @@ -229,19 +229,19 @@ function resolveChangedFiles(context, candidateFiles) { // source path), or set up a new one (including setting up watchers and registering // plugins) then return it export default function setupWatchingContext(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. + // 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) { // Add current css file as a context dependencies. contextDependencies.add(result.opts.from) @@ -299,7 +299,7 @@ export default function setupWatchingContext(configOrPath) { registerDependency({ type: 'dependency', file: touchFile }) } - if (tailwindDirectives.size > 0) { + if (tailwindDirectives.size > 0 || applyDirectives.size > 0) { for (let changedContent of resolvedChangedContent(context, candidateFiles)) { context.changedContent.push(changedContent) } diff --git a/src/processTailwindFeatures.js b/src/processTailwindFeatures.js index 8a6d22dae744..fc0314d15561 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) + const { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root) - let context = setupContext({ + const context = setupContext({ tailwindDirectives, + applyDirectives, registerDependency(dependency) { result.messages.push({ plugin: 'tailwindcss', diff --git a/tests/apply.test.js b/tests/apply.test.js index c74bb2875f5d..c50cf3707ee5 100644 --- a/tests/apply.test.js +++ b/tests/apply.test.js @@ -774,3 +774,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; + } + `) + }) +}) From 74a6b69481ec064ffa98d0ae442500f5591971d4 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 3 Jan 2022 18:50:28 -0500 Subject: [PATCH 2/7] Use let We use it more consistently --- src/processTailwindFeatures.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/processTailwindFeatures.js b/src/processTailwindFeatures.js index fc0314d15561..7c622205b623 100644 --- a/src/processTailwindFeatures.js +++ b/src/processTailwindFeatures.js @@ -12,9 +12,9 @@ import { issueFlagNotices } from './featureFlags' export default function processTailwindFeatures(setupContext) { return function (root, result) { - const { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root) + let { tailwindDirectives, applyDirectives } = normalizeTailwindDirectives(root) - const context = setupContext({ + let context = setupContext({ tailwindDirectives, applyDirectives, registerDependency(dependency) { From 85e4f22249e8c433b9e29843fac6aa5d4d2d8780 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 3 Jan 2022 18:50:49 -0500 Subject: [PATCH 3/7] Remove early return To match the style of the surrounding code --- src/lib/normalizeTailwindDirectives.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/normalizeTailwindDirectives.js b/src/lib/normalizeTailwindDirectives.js index 4d09f96806f5..24e3fa95387b 100644 --- a/src/lib/normalizeTailwindDirectives.js +++ b/src/lib/normalizeTailwindDirectives.js @@ -8,8 +8,8 @@ export default function normalizeTailwindDirectives(root) { root.walkAtRules((atRule) => { if (atRule.name === 'apply') { applyDirectives.add(atRule) - return } + if (atRule.name === 'import') { if (atRule.params === '"tailwindcss/base"' || atRule.params === "'tailwindcss/base'") { atRule.name = 'tailwind' From 3a2551e05238e72a261d7e0e54e12a1c78b9ec60 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 3 Jan 2022 18:51:29 -0500 Subject: [PATCH 4/7] 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. --- src/lib/normalizeTailwindDirectives.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/normalizeTailwindDirectives.js b/src/lib/normalizeTailwindDirectives.js index 24e3fa95387b..4ca1045138a5 100644 --- a/src/lib/normalizeTailwindDirectives.js +++ b/src/lib/normalizeTailwindDirectives.js @@ -79,5 +79,5 @@ export default function normalizeTailwindDirectives(root) { } } - return { tailwindDirectives, layerDirectives, applyDirectives } + return { tailwindDirectives, applyDirectives } } From 679c568faf9cba4318385339db2a77f5d875d920 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 3 Jan 2022 18:52:48 -0500 Subject: [PATCH 5/7] Use let --- src/lib/normalizeTailwindDirectives.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/normalizeTailwindDirectives.js b/src/lib/normalizeTailwindDirectives.js index 4ca1045138a5..a60d217e22a6 100644 --- a/src/lib/normalizeTailwindDirectives.js +++ b/src/lib/normalizeTailwindDirectives.js @@ -1,9 +1,9 @@ import log from '../util/log' export default function normalizeTailwindDirectives(root) { - const tailwindDirectives = new Set() - const layerDirectives = new Set() - const applyDirectives = new Set() + let tailwindDirectives = new Set() + let layerDirectives = new Set() + let applyDirectives = new Set() root.walkAtRules((atRule) => { if (atRule.name === 'apply') { From 2a23201ee245e9a2c6aea35c00ce769536f3253c Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Mon, 3 Jan 2022 18:56:17 -0500 Subject: [PATCH 6/7] Update changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 From 7e3387363ae929c4d9bbd108579f331472a8aaf4 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Tue, 4 Jan 2022 14:12:06 +0100 Subject: [PATCH 7/7] fix typo And re-format comments --- src/lib/setupTrackingContext.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib/setupTrackingContext.js b/src/lib/setupTrackingContext.js index 4cf7b3cc48c1..49050fd3bdca 100644 --- a/src/lib/setupTrackingContext.js +++ b/src/lib/setupTrackingContext.js @@ -119,11 +119,12 @@ export default function setupTrackingContext(configOrPath) { let contextDependencies = new Set(configDependencies) - // 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 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)