From ae6a8d532b225ad7f62ecaecd5769582544f2084 Mon Sep 17 00:00:00 2001 From: Georg Ledermann Date: Tue, 16 Jul 2024 15:34:20 +0200 Subject: [PATCH 1/5] Fix extracting utilities from slim/pug templates (#14006) A class name starting with number like `2xl:bg-red-500` must not be removed. Resolves #14005 --- src/lib/defaultExtractor.js | 2 +- tests/default-extractor.test.js | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib/defaultExtractor.js b/src/lib/defaultExtractor.js index fdcd8dd5d214..8f89596313ce 100644 --- a/src/lib/defaultExtractor.js +++ b/src/lib/defaultExtractor.js @@ -32,7 +32,7 @@ export function defaultExtractor(context) { // If the next segment is a number, discard both, for example seeing // `px-1` and `5` means the real candidate was `px-1.5` which is already // captured. - let next = parseInt(segments[idx + 1]) + let next = Number(segments[idx + 1]) if (isNaN(next)) { results.push(segment) } else { diff --git a/tests/default-extractor.test.js b/tests/default-extractor.test.js index d99069197d60..0cac75d0c299 100644 --- a/tests/default-extractor.test.js +++ b/tests/default-extractor.test.js @@ -476,6 +476,16 @@ test('classes in slim templates', async () => { expect(extractions).toContain('text-gray-500') }) +test('classes in slim templates starting with number', async () => { + const extractions = defaultExtractor(` + .bg-green-300.2xl:bg-red-300 + '(Look mom, no closing tag!) + `) + + expect(extractions).toContain('bg-green-300') + expect(extractions).toContain('2xl:bg-red-300') +}) + test("classes with fractional numeric values don't also generate the whole number utility", async () => { const extractions = defaultExtractor(`
Hello world!
From daa526608111698ec9f5639a8e2e461d7a8f2ebe Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 16 Jul 2024 09:36:07 -0400 Subject: [PATCH 2/5] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b50934dd8c7..34eadbde36aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Nothing yet! +- Fix detection of some utilities in Slim/Pug templates ([#14006](https://github.com/tailwindlabs/tailwindcss/pull/14006)) ## [3.4.5] - 2024-07-15 From 9c29e47c5f0c8dc241b559796241c8b746b905ee Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 16 Jul 2024 09:37:15 -0400 Subject: [PATCH 3/5] 3.4.6 --- CHANGELOG.md | 9 ++++++++- package-lock.json | 4 ++-- package.json | 2 +- standalone-cli/package-lock.json | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34eadbde36aa..964754dc3295 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Nothing yet! + +## [3.4.6] - 2024-07-16 + +### Fixed + - Fix detection of some utilities in Slim/Pug templates ([#14006](https://github.com/tailwindlabs/tailwindcss/pull/14006)) ## [3.4.5] - 2024-07-15 @@ -2395,7 +2401,8 @@ No release notes - Everything! -[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.5...HEAD +[unreleased]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.6...HEAD +[3.4.6]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.5...v3.4.6 [3.4.5]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.4...v3.4.5 [3.4.4]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.3...v3.4.4 [3.4.3]: https://github.com/tailwindlabs/tailwindcss/compare/v3.4.2...v3.4.3 diff --git a/package-lock.json b/package-lock.json index d649fab92f7f..a04a12bca3c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "tailwindcss", - "version": "3.4.5", + "version": "3.4.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "tailwindcss", - "version": "3.4.5", + "version": "3.4.6", "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", diff --git a/package.json b/package.json index 3c5d64a89a73..484886923f44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tailwindcss", - "version": "3.4.5", + "version": "3.4.6", "description": "A utility-first CSS framework for rapidly building custom user interfaces.", "license": "MIT", "main": "lib/index.js", diff --git a/standalone-cli/package-lock.json b/standalone-cli/package-lock.json index f080054b6088..e894c1fdd356 100644 --- a/standalone-cli/package-lock.json +++ b/standalone-cli/package-lock.json @@ -25,7 +25,7 @@ }, "..": { "name": "tailwindcss", - "version": "3.4.5", + "version": "3.4.6", "dev": true, "license": "MIT", "dependencies": { From 0573c0769af1bf42433cb1992490f3789725f27c Mon Sep 17 00:00:00 2001 From: Josh Wilson Date: Tue, 16 Jul 2024 10:51:45 -0400 Subject: [PATCH 4/5] Loosen :is() wrapping rules in applyImportantSelector for more readable output. (#13900) --- src/util/applyImportantSelector.js | 11 +++++----- tests/util/apply-important-selector.test.js | 23 ++++++++++----------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/util/applyImportantSelector.js b/src/util/applyImportantSelector.js index ff9ec4f4b343..07302f94d5f6 100644 --- a/src/util/applyImportantSelector.js +++ b/src/util/applyImportantSelector.js @@ -5,13 +5,12 @@ export function applyImportantSelector(selector, important) { let sel = parser().astSync(selector) sel.each((sel) => { - // Wrap with :is if it's not already wrapped - let isWrapped = - sel.nodes[0].type === 'pseudo' && - sel.nodes[0].value === ':is' && - sel.nodes.every((node) => node.type !== 'combinator') + // For nesting, we only need to wrap a selector with :is() if it has a top-level combinator, + // e.g. `.dark .text-white`, to be independent of DOM order. Any other selector, including + // combinators inside of pseudos like `:where()`, are ok to nest. + let shouldWrap = sel.nodes.some((node) => node.type === 'combinator') - if (!isWrapped) { + if (shouldWrap) { sel.nodes = [ parser.pseudo({ value: ':is', diff --git a/tests/util/apply-important-selector.test.js b/tests/util/apply-important-selector.test.js index f5d3697cf88c..cd971b92c732 100644 --- a/tests/util/apply-important-selector.test.js +++ b/tests/util/apply-important-selector.test.js @@ -2,24 +2,23 @@ import { applyImportantSelector } from '../../src/util/applyImportantSelector' it.each` before | after - ${'.foo'} | ${'#app :is(.foo)'} + ${'.foo'} | ${'#app .foo'} ${'.foo .bar'} | ${'#app :is(.foo .bar)'} - ${'.foo:hover'} | ${'#app :is(.foo:hover)'} + ${'.foo:hover'} | ${'#app .foo:hover'} ${'.foo .bar:hover'} | ${'#app :is(.foo .bar:hover)'} - ${'.foo::before'} | ${'#app :is(.foo)::before'} - ${'.foo::before'} | ${'#app :is(.foo)::before'} - ${'.foo::file-selector-button'} | ${'#app :is(.foo)::file-selector-button'} - ${'.foo::-webkit-progress-bar'} | ${'#app :is(.foo)::-webkit-progress-bar'} - ${'.foo:hover::before'} | ${'#app :is(.foo:hover)::before'} + ${'.foo::before'} | ${'#app .foo::before'} + ${'.foo::file-selector-button'} | ${'#app .foo::file-selector-button'} + ${'.foo::-webkit-progress-bar'} | ${'#app .foo::-webkit-progress-bar'} + ${'.foo:hover::before'} | ${'#app .foo:hover::before'} ${':is(:where(.dark) :is(:where([dir="rtl"]) .foo::before))'} | ${'#app :is(:where(.dark) :is(:where([dir="rtl"]) .foo))::before'} ${':is(:where(.dark) .foo) .bar'} | ${'#app :is(:is(:where(.dark) .foo) .bar)'} ${':is(.foo) :is(.bar)'} | ${'#app :is(:is(.foo) :is(.bar))'} ${':is(.foo)::before'} | ${'#app :is(.foo)::before'} - ${'.foo:before'} | ${'#app :is(.foo):before'} - ${'.foo::some-uknown-pseudo'} | ${'#app :is(.foo)::some-uknown-pseudo'} - ${'.foo::some-uknown-pseudo:hover'} | ${'#app :is(.foo)::some-uknown-pseudo:hover'} - ${'.foo:focus::some-uknown-pseudo:hover'} | ${'#app :is(.foo:focus)::some-uknown-pseudo:hover'} - ${'.foo:hover::some-uknown-pseudo:focus'} | ${'#app :is(.foo:hover)::some-uknown-pseudo:focus'} + ${'.foo:before'} | ${'#app .foo:before'} + ${'.foo::some-uknown-pseudo'} | ${'#app .foo::some-uknown-pseudo'} + ${'.foo::some-uknown-pseudo:hover'} | ${'#app .foo::some-uknown-pseudo:hover'} + ${'.foo:focus::some-uknown-pseudo:hover'} | ${'#app .foo:focus::some-uknown-pseudo:hover'} + ${'.foo:hover::some-uknown-pseudo:focus'} | ${'#app .foo:hover::some-uknown-pseudo:focus'} `('should generate "$after" from "$before"', ({ before, after }) => { expect(applyImportantSelector(before, '#app')).toEqual(after) }) From d622977b2a3308703e1cb105f3eeb555da31877f Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 16 Jul 2024 10:52:51 -0400 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 964754dc3295..6156ddff6100 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix detection of some utilities in Slim/Pug templates ([#14006](https://github.com/tailwindlabs/tailwindcss/pull/14006)) +### Changed + +- Loosen `:is()` wrapping rules when using an important selector ([#13900](https://github.com/tailwindlabs/tailwindcss/pull/13900)) + ## [3.4.5] - 2024-07-15 ### Fixed