diff --git a/src/lib/detectNesting.js b/src/lib/detectNesting.js new file mode 100644 index 000000000..5a3181a27 --- /dev/null +++ b/src/lib/detectNesting.js @@ -0,0 +1,20 @@ +export default function (_context) { + return (root, result) => { + let found = false + + root.walkRules((rule) => { + if (found) return false + + rule.walkRules((nestedRule) => { + found = true + nestedRule.warn( + result, + // TODO: Improve this warning message + 'Nested CSS detected, checkout the docs on how to support nesting: https://tailwindcss.com/docs/using-with-preprocessors#nesting' + ) + + return false + }) + }) + } +} diff --git a/src/processTailwindFeatures.js b/src/processTailwindFeatures.js index 2ac6374ce..de28a8944 100644 --- a/src/processTailwindFeatures.js +++ b/src/processTailwindFeatures.js @@ -5,6 +5,7 @@ import evaluateTailwindFunctions from './lib/evaluateTailwindFunctions' import substituteScreenAtRules from './lib/substituteScreenAtRules' import resolveDefaultsAtRules from './lib/resolveDefaultsAtRules' import collapseAdjacentRules from './lib/collapseAdjacentRules' +import detectNesting from './lib/detectNesting' import { createContext } from './lib/setupContextUtils' export default function processTailwindFeatures(setupContext) { @@ -31,6 +32,7 @@ export default function processTailwindFeatures(setupContext) { ) } + detectNesting(context)(root, result) expandTailwindAtRules(context)(root, result) expandApplyAtRules(context)(root, result) evaluateTailwindFunctions(context)(root, result) diff --git a/tests/detect-nesting.test.js b/tests/detect-nesting.test.js new file mode 100644 index 000000000..35e30393d --- /dev/null +++ b/tests/detect-nesting.test.js @@ -0,0 +1,73 @@ +import { run, html, css } from './util/run' + +it('should warn when we detect nested css', () => { + let config = { + content: [{ raw: html`
` }], + } + + let input = css` + @tailwind utilities; + + .nested { + .example { + } + } + ` + + return run(input, config).then((result) => { + expect(result.messages).toHaveLength(1) + expect(result.messages).toMatchObject([ + { + type: 'warning', + text: 'Nested CSS detected, checkout the docs on how to support nesting: https://tailwindcss.com/docs/using-with-preprocessors#nesting', + }, + ]) + }) +}) + +it('should not warn when nesting a single rule inside a media query', () => { + let config = { + content: [{ raw: html`
` }], + } + + let input = css` + @tailwind utilities; + + @media (min-width: 768px) { + .nested { + } + } + ` + + return run(input, config).then((result) => { + expect(result.messages).toHaveLength(0) + expect(result.messages).toEqual([]) + }) +}) + +it('should only warn for the first detected nesting ', () => { + let config = { + content: [{ raw: html`
` }], + } + + let input = css` + @tailwind utilities; + + .nested { + .example { + } + + .other { + } + } + + .other { + .example { + } + } + ` + + return run(input, config).then((result) => { + expect(result.messages).toHaveLength(1) + }) +})