Skip to content

Commit cd0c308

Browse files
Improve sorting candidates containing numbers (#13507)
* implement custom `compare` for sorting purposes This `compare` function compares two strings. However, once a number is reached the numbers are compared as actual numbers instead of the string representation. E.g.: ``` p-1 p-2 p-10 p-20 ``` Will be sorted as expected in this order, instead of ``` p-1 p-10 p-2 p-20 ``` --- This should also make suggestions in the vscode extension more logical. * update tests to reflect order changes * update changelog * reset `i` correctly This makes the code more correct _and_ improves performance because the `Number(…)` will now always deal with numbers. On the tailwindcss.com codebase, sorting now goes from `~3.29ms` to `~3.10ms` * drop unreachable code In this branch, it's guaranteed that numbers are _different_ which means that they are never going to be the same thus unreachable code. When we compare two strings such as: ``` foo-123-bar foo-123-baz ``` Then all characters until the last character is the same character in both positions. This means that "numbers" that are the same in the same position will be compared as strings instead of numbers. But that is fine because they are the same anyway. * add fallback in case numbers are the same but strings are not This can happen if we are sorting `0123` and `123`. The `Number` representation will be equal, but the string is not. Will rarely or even never happen. But if it does, this makes it deterministic. * re-word comment * add more test cases with numbers in different spots with various lengths * Update CHANGELOG.md * cleanup, simplify which variables we increment This also gets rid of some explanation that can now be omitted entirely. --------- Co-authored-by: Adam Wathan <[email protected]>
1 parent b07cc4d commit cd0c308

File tree

6 files changed

+283
-107
lines changed

6 files changed

+283
-107
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1414
## Changed
1515

1616
- Use `rem` units for breakpoints by default instead of `px` ([#13469](https://github.com/tailwindlabs/tailwindcss/pull/13469))
17+
- Use natural sorting when sorting classes ([#13507](https://github.com/tailwindlabs/tailwindcss/pull/13507))
1718

1819
## [4.0.0-alpha.14] - 2024-04-09
1920

packages/tailwindcss/src/__snapshots__/utilities.test.ts.snap

+49-49
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ exports[`border-* 1`] = `
1818
border-width: 0;
1919
}
2020
21-
.border-123 {
22-
border-style: var(--tw-border-style);
23-
border-width: 123px;
24-
}
25-
2621
.border-2 {
2722
border-style: var(--tw-border-style);
2823
border-width: 2px;
@@ -33,6 +28,11 @@ exports[`border-* 1`] = `
3328
border-width: 4px;
3429
}
3530
31+
.border-123 {
32+
border-style: var(--tw-border-style);
33+
border-width: 123px;
34+
}
35+
3636
.border-\\[12px\\] {
3737
border-style: var(--tw-border-style);
3838
border-width: 12px;
@@ -131,11 +131,6 @@ exports[`border-b-* 1`] = `
131131
border-bottom-width: 0;
132132
}
133133
134-
.border-b-123 {
135-
border-bottom-style: var(--tw-border-style);
136-
border-bottom-width: 123px;
137-
}
138-
139134
.border-b-2 {
140135
border-bottom-style: var(--tw-border-style);
141136
border-bottom-width: 2px;
@@ -146,6 +141,11 @@ exports[`border-b-* 1`] = `
146141
border-bottom-width: 4px;
147142
}
148143
144+
.border-b-123 {
145+
border-bottom-style: var(--tw-border-style);
146+
border-bottom-width: 123px;
147+
}
148+
149149
.border-b-\\[12px\\] {
150150
border-bottom-style: var(--tw-border-style);
151151
border-bottom-width: 12px;
@@ -244,11 +244,6 @@ exports[`border-e-* 1`] = `
244244
border-inline-end-width: 0;
245245
}
246246
247-
.border-e-123 {
248-
border-inline-end-style: var(--tw-border-style);
249-
border-inline-end-width: 123px;
250-
}
251-
252247
.border-e-2 {
253248
border-inline-end-style: var(--tw-border-style);
254249
border-inline-end-width: 2px;
@@ -259,6 +254,11 @@ exports[`border-e-* 1`] = `
259254
border-inline-end-width: 4px;
260255
}
261256
257+
.border-e-123 {
258+
border-inline-end-style: var(--tw-border-style);
259+
border-inline-end-width: 123px;
260+
}
261+
262262
.border-e-\\[12px\\] {
263263
border-inline-end-style: var(--tw-border-style);
264264
border-inline-end-width: 12px;
@@ -357,11 +357,6 @@ exports[`border-l-* 1`] = `
357357
border-left-width: 0;
358358
}
359359
360-
.border-l-123 {
361-
border-left-style: var(--tw-border-style);
362-
border-left-width: 123px;
363-
}
364-
365360
.border-l-2 {
366361
border-left-style: var(--tw-border-style);
367362
border-left-width: 2px;
@@ -372,6 +367,11 @@ exports[`border-l-* 1`] = `
372367
border-left-width: 4px;
373368
}
374369
370+
.border-l-123 {
371+
border-left-style: var(--tw-border-style);
372+
border-left-width: 123px;
373+
}
374+
375375
.border-l-\\[12px\\] {
376376
border-left-style: var(--tw-border-style);
377377
border-left-width: 12px;
@@ -470,11 +470,6 @@ exports[`border-r-* 1`] = `
470470
border-right-width: 0;
471471
}
472472
473-
.border-r-123 {
474-
border-right-style: var(--tw-border-style);
475-
border-right-width: 123px;
476-
}
477-
478473
.border-r-2 {
479474
border-right-style: var(--tw-border-style);
480475
border-right-width: 2px;
@@ -485,6 +480,11 @@ exports[`border-r-* 1`] = `
485480
border-right-width: 4px;
486481
}
487482
483+
.border-r-123 {
484+
border-right-style: var(--tw-border-style);
485+
border-right-width: 123px;
486+
}
487+
488488
.border-r-\\[12px\\] {
489489
border-right-style: var(--tw-border-style);
490490
border-right-width: 12px;
@@ -583,11 +583,6 @@ exports[`border-s-* 1`] = `
583583
border-inline-start-width: 0;
584584
}
585585
586-
.border-s-123 {
587-
border-inline-start-style: var(--tw-border-style);
588-
border-inline-start-width: 123px;
589-
}
590-
591586
.border-s-2 {
592587
border-inline-start-style: var(--tw-border-style);
593588
border-inline-start-width: 2px;
@@ -598,6 +593,11 @@ exports[`border-s-* 1`] = `
598593
border-inline-start-width: 4px;
599594
}
600595
596+
.border-s-123 {
597+
border-inline-start-style: var(--tw-border-style);
598+
border-inline-start-width: 123px;
599+
}
600+
601601
.border-s-\\[12px\\] {
602602
border-inline-start-style: var(--tw-border-style);
603603
border-inline-start-width: 12px;
@@ -696,11 +696,6 @@ exports[`border-t-* 1`] = `
696696
border-top-width: 0;
697697
}
698698
699-
.border-t-123 {
700-
border-top-style: var(--tw-border-style);
701-
border-top-width: 123px;
702-
}
703-
704699
.border-t-2 {
705700
border-top-style: var(--tw-border-style);
706701
border-top-width: 2px;
@@ -711,6 +706,11 @@ exports[`border-t-* 1`] = `
711706
border-top-width: 4px;
712707
}
713708
709+
.border-t-123 {
710+
border-top-style: var(--tw-border-style);
711+
border-top-width: 123px;
712+
}
713+
714714
.border-t-\\[12px\\] {
715715
border-top-style: var(--tw-border-style);
716716
border-top-width: 12px;
@@ -813,13 +813,6 @@ exports[`border-x-* 1`] = `
813813
border-right-width: 0;
814814
}
815815
816-
.border-x-123 {
817-
border-left-style: var(--tw-border-style);
818-
border-right-style: var(--tw-border-style);
819-
border-left-width: 123px;
820-
border-right-width: 123px;
821-
}
822-
823816
.border-x-2 {
824817
border-left-style: var(--tw-border-style);
825818
border-right-style: var(--tw-border-style);
@@ -834,6 +827,13 @@ exports[`border-x-* 1`] = `
834827
border-right-width: 4px;
835828
}
836829
830+
.border-x-123 {
831+
border-left-style: var(--tw-border-style);
832+
border-right-style: var(--tw-border-style);
833+
border-left-width: 123px;
834+
border-right-width: 123px;
835+
}
836+
837837
.border-x-\\[12px\\] {
838838
border-left-style: var(--tw-border-style);
839839
border-right-style: var(--tw-border-style);
@@ -958,13 +958,6 @@ exports[`border-y-* 1`] = `
958958
border-bottom-width: 0;
959959
}
960960
961-
.border-y-123 {
962-
border-top-style: var(--tw-border-style);
963-
border-bottom-style: var(--tw-border-style);
964-
border-top-width: 123px;
965-
border-bottom-width: 123px;
966-
}
967-
968961
.border-y-2 {
969962
border-top-style: var(--tw-border-style);
970963
border-bottom-style: var(--tw-border-style);
@@ -979,6 +972,13 @@ exports[`border-y-* 1`] = `
979972
border-bottom-width: 4px;
980973
}
981974
975+
.border-y-123 {
976+
border-top-style: var(--tw-border-style);
977+
border-bottom-style: var(--tw-border-style);
978+
border-top-width: 123px;
979+
border-bottom-width: 123px;
980+
}
981+
982982
.border-y-\\[12px\\] {
983983
border-top-style: var(--tw-border-style);
984984
border-bottom-style: var(--tw-border-style);

packages/tailwindcss/src/compile.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { rule, type AstNode, type Rule } from './ast'
22
import { type Candidate, type Variant } from './candidate'
33
import { type DesignSystem } from './design-system'
44
import GLOBAL_PROPERTY_ORDER from './property-order'
5+
import { compare } from './utils/compare'
56
import { escape } from './utils/escape'
67
import type { Variants } from './variants'
78

@@ -87,7 +88,7 @@ export function compileCandidates(
8788
// Sort by most properties first, then by least properties
8889
zSorting.properties.length - aSorting.properties.length ||
8990
// Sort alphabetically
90-
(aSorting.candidate < zSorting.candidate ? -1 : 1)
91+
compare(aSorting.candidate, zSorting.candidate)
9192
)
9293
})
9394

0 commit comments

Comments
 (0)