Skip to content

Commit 074736c

Browse files
authored
Avoid over-extracting utilities from candidates with decimal values (#13959)
* Avoid over-extracting utilities from candidates with decimal values Prevent candidates like `px-1.5` from generating both the `px-1.5` class and the `px-1` class. * Update CHANGELOG.md --------- Co-authored-by: Adam Wathan <[email protected]>
1 parent 588a822 commit 074736c

File tree

3 files changed

+39
-3
lines changed

3 files changed

+39
-3
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Disable automatic `var()` injection for anchor properties ([#13826](https://github.com/tailwindlabs/tailwindcss/pull/13826))
1313
- Use no value instead of `blur(0px)` for `backdrop-blur-none` and `blur-none` utilities ([#13830](https://github.com/tailwindlabs/tailwindcss/pull/13830))
1414
- Add `.mts` and `.cts` config file detection ([#13940](https://github.com/tailwindlabs/tailwindcss/pull/13940))
15+
- Don't generate utilities like `px-1` unnecessarily when using utilities like `px-1.5` ([#13959](https://github.com/tailwindlabs/tailwindcss/pull/13959))
1516

1617
## [3.4.4] - 2024-06-05
1718

src/lib/defaultExtractor.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as regex from './regex'
2+
import { splitAtTopLevelOnly } from '../util/splitAtTopLevelOnly'
23

34
export function defaultExtractor(context) {
45
let patterns = Array.from(buildRegExps(context))
@@ -16,6 +17,30 @@ export function defaultExtractor(context) {
1617
}
1718
}
1819

20+
// Extract any subclasses from languages like Slim and Pug, eg:
21+
// div.flex.px-5.underline
22+
for (let result of results.slice()) {
23+
let segments = splitAtTopLevelOnly(result, '.')
24+
25+
for (let idx = 0; idx < segments.length; idx++) {
26+
let segment = segments[idx]
27+
if (idx >= segments.length - 1) {
28+
results.push(segment)
29+
continue
30+
}
31+
32+
// If the next segment is a number, discard both, for example seeing
33+
// `px-1` and `5` means the real candidate was `px-1.5` which is already
34+
// captured.
35+
let next = parseInt(segments[idx + 1])
36+
if (isNaN(next)) {
37+
results.push(segment)
38+
} else {
39+
idx++
40+
}
41+
}
42+
}
43+
1944
return results
2045
}
2146
}
@@ -127,9 +152,6 @@ function* buildRegExps(context) {
127152
utility,
128153
])
129154
}
130-
131-
// 5. Inner matches
132-
yield /[^<>"'`\s.(){}[\]#=%$]*[^<>"'`\s.(){}[\]#=%:$]/g
133155
}
134156

135157
// We want to capture any "special" characters

tests/default-extractor.test.js

+13
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,19 @@ test('classes in slim templates', async () => {
476476
expect(extractions).toContain('text-gray-500')
477477
})
478478

479+
test("classes with fractional numeric values don't also generate the whole number utility", async () => {
480+
const extractions = defaultExtractor(`
481+
<div class="px-1.5 py-2.75">Hello world!</div>
482+
`)
483+
484+
expect(extractions).toContain('px-1.5')
485+
expect(extractions).toContain('py-2.75')
486+
expect(extractions).not.toContain('px-1')
487+
expect(extractions).not.toContain('5')
488+
expect(extractions).not.toContain('py-2')
489+
expect(extractions).not.toContain('75')
490+
})
491+
479492
test('multi-word + arbitrary values + quotes', async () => {
480493
const extractions = defaultExtractor(`
481494
grid-cols-['repeat(2)']

0 commit comments

Comments
 (0)