Skip to content

Commit

Permalink
Only emit utility/component variants when those layers exist (#7066)
Browse files Browse the repository at this point in the history
  • Loading branch information
thecrypticace committed Jan 14, 2022
1 parent 8293c2d commit e292888
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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
Expand Down
31 changes: 23 additions & 8 deletions src/lib/expandTailwindAtRules.js
Expand Up @@ -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()
}

Expand All @@ -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',
])
Expand Down
6 changes: 6 additions & 0 deletions src/lib/generateRules.js
Expand Up @@ -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,
Expand Down
74 changes: 73 additions & 1 deletion tests/variants.test.js
@@ -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 = {
Expand Down Expand Up @@ -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;
}
}
}
`)
})
})

0 comments on commit e292888

Please sign in to comment.