Only emit utility/component variants when those layers exist (#7066)

This commit is contained in:
Jordan Pittman 2022-01-14 10:20:43 -05:00 committed by GitHub
parent 8293c2d33d
commit e2928883e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 9 deletions

View File

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Show warnings for invalid content config ([#7065](https://github.com/tailwindlabs/tailwindcss/pull/7065))
### Fixed
- Only emit utility/component variants when those layers exist ([#7066](https://github.com/tailwindlabs/tailwindcss/pull/7066))
## [3.0.13] - 2022-01-11
### Fixed

View File

@ -205,9 +205,6 @@ export default function expandTailwindAtRules(context) {
if (layerNodes.base) {
layerNodes.base.before(cloneNodes([...baseNodes, ...defaultNodes], layerNodes.base.source))
}
if (layerNodes.base) {
layerNodes.base.remove()
}
@ -221,16 +218,34 @@ export default function expandTailwindAtRules(context) {
layerNodes.utilities.remove()
}
// We do post-filtering to not alter the emitted order of the variants
const variantNodes = Array.from(screenNodes).filter((node) => {
const parentLayer = node.raws.tailwind?.parentLayer
if (parentLayer === 'components') {
return layerNodes.components !== null
}
if (parentLayer === 'utilities') {
return layerNodes.utilities !== null
}
return true
})
if (layerNodes.variants) {
layerNodes.variants.before(cloneNodes([...screenNodes], layerNodes.variants.source))
layerNodes.variants.before(cloneNodes(variantNodes, layerNodes.variants.source))
layerNodes.variants.remove()
} else {
root.append(cloneNodes([...screenNodes], root.source))
} else if (variantNodes.length > 0) {
root.append(cloneNodes(variantNodes, root.source))
}
// If we've got a utility layer and no utilities are generated there's likely something wrong
// TODO: Detect utility variants only
if (layerNodes.utilities && utilityNodes.size === 0 && screenNodes.size === 0) {
const hasUtilityVariants = variantNodes.some(
(node) => node.raws.tailwind?.parentLayer === 'utilities'
)
if (layerNodes.utilities && utilityNodes.size === 0 && !hasUtilityVariants) {
log.warn('content-problems', [
'No utilities were generated there is likely a problem with the `content` key in the tailwind config. For more information see the documentation: https://tailwindcss.com/docs/content-configuration',
])

View File

@ -216,6 +216,12 @@ function applyVariant(variant, matches, context) {
})
}
// This tracks the originating layer for the variant
// For example:
// .sm:underline {} is a variant of something in the utilities layer
// .sm:container {} is a variant of the container component
clone.nodes[0].raws.tailwind = { parentLayer: meta.layer }
let withOffset = [
{
...meta,

View File

@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'
import { run, css, html } from './util/run'
import { run, css, html, defaults } from './util/run'
test('variants', () => {
let config = {
@ -467,3 +467,75 @@ it('should be possible to use responsive modifiers that are defined with special
`)
})
})
it('including just the base layer should not produce variants', () => {
let config = {
content: [{ raw: html`<div class="sm:container sm:underline"></div>` }],
corePlugins: { preflight: false },
}
return run('@tailwind base', config).then((result) => {
return expect(result.css).toMatchFormattedCss(
css`
${defaults}
`
)
})
})
it('variants for components should not be produced in a file without a components layer', () => {
let config = {
content: [{ raw: html`<div class="sm:container sm:underline"></div>` }],
}
return run('@tailwind utilities', config).then((result) => {
return expect(result.css).toMatchFormattedCss(css`
@media (min-width: 640px) {
.sm\:underline {
text-decoration-line: underline;
}
}
`)
})
})
it('variants for utilities should not be produced in a file without a utilities layer', () => {
let config = {
content: [{ raw: html`<div class="sm:container sm:underline"></div>` }],
}
return run('@tailwind components', config).then((result) => {
return expect(result.css).toMatchFormattedCss(css`
@media (min-width: 640px) {
.sm\:container {
width: 100%;
}
@media (min-width: 640px) {
.sm\:container {
max-width: 640px;
}
}
@media (min-width: 768px) {
.sm\:container {
max-width: 768px;
}
}
@media (min-width: 1024px) {
.sm\:container {
max-width: 1024px;
}
}
@media (min-width: 1280px) {
.sm\:container {
max-width: 1280px;
}
}
@media (min-width: 1536px) {
.sm\:container {
max-width: 1536px;
}
}
}
`)
})
})