From d2911266ef87af395524cccf415ac8eb09e34356 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 11 Mar 2022 12:48:57 +0100 Subject: [PATCH 1/3] fix little typo --- tests/basic-usage.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basic-usage.test.js b/tests/basic-usage.test.js index c013f5b08c6d..f911cd366919 100644 --- a/tests/basic-usage.test.js +++ b/tests/basic-usage.test.js @@ -349,7 +349,7 @@ it('does not produce duplicate output when seeing variants preceding a wildcard }) }) -it('it can parse box shadows with variables', () => { +it('can parse box shadows with variables', () => { let config = { content: [{ raw: html`
` }], theme: { From 774c1d28dfd1587f8e60d2e4fa3ae2ad5af65027 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 11 Mar 2022 12:49:16 +0100 Subject: [PATCH 2/3] ensure that `div:not(.unknown-class)` gets generated --- src/lib/setupContextUtils.js | 26 +++++++++++++++++++++----- tests/basic-usage.test.js | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/lib/setupContextUtils.js b/src/lib/setupContextUtils.js index ed1cdba61ae9..f2dc6a516b2e 100644 --- a/src/lib/setupContextUtils.js +++ b/src/lib/setupContextUtils.js @@ -85,12 +85,18 @@ function parseStyles(styles) { }) } -function getClasses(selector) { +function getClasses(selector, mutate) { let parser = selectorParser((selectors) => { let allClasses = [] + + if (mutate) { + mutate(selectors) + } + selectors.walkClasses((classNode) => { allClasses.push(classNode.value) }) + return allClasses }) return parser.transformSync(selector) @@ -101,8 +107,20 @@ function extractCandidates(node, state = { containsNonOnDemandable: false }, dep // Handle normal rules if (node.type === 'rule') { + // Ignore everything inside a :not(...). This allows you to write code like + // `div:not(.foo)`. If `.foo` is never found in your code, then we used to + // not generated it. But now we will ignore everything inside a `:not`, so + // that it still gets generated. + function ignoreNot(selectors) { + selectors.walkPseudos((pseudo) => { + if (pseudo.value === ':not') { + pseudo.remove() + } + }) + } + for (let selector of node.selectors) { - let classCandidates = getClasses(selector) + let classCandidates = getClasses(selector, ignoreNot) // At least one of the selectors contains non-"on-demandable" candidates. if (classCandidates.length === 0) { state.containsNonOnDemandable = true @@ -117,9 +135,7 @@ function extractCandidates(node, state = { containsNonOnDemandable: false }, dep // Handle at-rules (which contains nested rules) else if (node.type === 'atrule') { node.walkRules((rule) => { - for (let classCandidate of rule.selectors.flatMap((selector) => - getClasses(selector, state, depth + 1) - )) { + for (let classCandidate of rule.selectors.flatMap((selector) => getClasses(selector))) { classes.push(classCandidate) } }) diff --git a/tests/basic-usage.test.js b/tests/basic-usage.test.js index f911cd366919..a574ffc60d0c 100644 --- a/tests/basic-usage.test.js +++ b/tests/basic-usage.test.js @@ -376,3 +376,28 @@ it('can parse box shadows with variables', () => { `) }) }) + +it('should generate styles using :not(.unknown-class) even if `.unknown-class` does not exist', () => { + let config = { + content: [{ raw: html`
` }], + corePlugins: { preflight: false }, + } + + let input = css` + @tailwind components; + + @layer components { + div:not(.unknown-class) { + color: red; + } + } + ` + + return run(input, config).then((result) => { + expect(result.css).toMatchFormattedCss(css` + div:not(.unknown-class) { + color: red; + } + `) + }) +}) From 325ac2ffdad3e655eb0228e6b1e46b5ca88f2c87 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 11 Mar 2022 12:57:55 +0100 Subject: [PATCH 3/3] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a5e1141ff60..11b67925dd1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Correctly parse and prefix animation names with dots ([#7163](https://github.com/tailwindlabs/tailwindcss/pull/7163)) - Fix extraction from template literal/function with array ([#7481](https://github.com/tailwindlabs/tailwindcss/pull/7481)) - Don't output unparsable arbitrary values ([#7789](https://github.com/tailwindlabs/tailwindcss/pull/7789)) +- Fix generation of `div:not(.foo)` if `.foo` is never defined ([#7815](https://github.com/tailwindlabs/tailwindcss/pull/7815)) ### Changed