Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow all classes for @apply #6580

Merged
merged 8 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 6 additions & 1 deletion src/lib/normalizeTailwindDirectives.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -74,5 +79,5 @@ export default function normalizeTailwindDirectives(root) {
}
}

return tailwindDirectives
return { tailwindDirectives, applyDirectives }
}
21 changes: 11 additions & 10 deletions src/lib/setupTrackingContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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.
Expand Down
3 changes: 2 additions & 1 deletion src/processTailwindFeatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
35 changes: 35 additions & 0 deletions tests/apply.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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`<div class="foo"></div>` }],
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;
}
`)
})
})