Skip to content

Commit

Permalink
Improve sorting candidates containing numbers (#13507)
Browse files Browse the repository at this point in the history
* 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 <adam.wathan@gmail.com>
  • Loading branch information
RobinMalfait and adamwathan committed Apr 15, 2024
1 parent b07cc4d commit cd0c308
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 107 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Changed

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

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

Expand Down
98 changes: 49 additions & 49 deletions packages/tailwindcss/src/__snapshots__/utilities.test.ts.snap
Expand Up @@ -18,11 +18,6 @@ exports[`border-* 1`] = `
border-width: 0;
}
.border-123 {
border-style: var(--tw-border-style);
border-width: 123px;
}
.border-2 {
border-style: var(--tw-border-style);
border-width: 2px;
Expand All @@ -33,6 +28,11 @@ exports[`border-* 1`] = `
border-width: 4px;
}
.border-123 {
border-style: var(--tw-border-style);
border-width: 123px;
}
.border-\\[12px\\] {
border-style: var(--tw-border-style);
border-width: 12px;
Expand Down Expand Up @@ -131,11 +131,6 @@ exports[`border-b-* 1`] = `
border-bottom-width: 0;
}
.border-b-123 {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 123px;
}
.border-b-2 {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 2px;
Expand All @@ -146,6 +141,11 @@ exports[`border-b-* 1`] = `
border-bottom-width: 4px;
}
.border-b-123 {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 123px;
}
.border-b-\\[12px\\] {
border-bottom-style: var(--tw-border-style);
border-bottom-width: 12px;
Expand Down Expand Up @@ -244,11 +244,6 @@ exports[`border-e-* 1`] = `
border-inline-end-width: 0;
}
.border-e-123 {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 123px;
}
.border-e-2 {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 2px;
Expand All @@ -259,6 +254,11 @@ exports[`border-e-* 1`] = `
border-inline-end-width: 4px;
}
.border-e-123 {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 123px;
}
.border-e-\\[12px\\] {
border-inline-end-style: var(--tw-border-style);
border-inline-end-width: 12px;
Expand Down Expand Up @@ -357,11 +357,6 @@ exports[`border-l-* 1`] = `
border-left-width: 0;
}
.border-l-123 {
border-left-style: var(--tw-border-style);
border-left-width: 123px;
}
.border-l-2 {
border-left-style: var(--tw-border-style);
border-left-width: 2px;
Expand All @@ -372,6 +367,11 @@ exports[`border-l-* 1`] = `
border-left-width: 4px;
}
.border-l-123 {
border-left-style: var(--tw-border-style);
border-left-width: 123px;
}
.border-l-\\[12px\\] {
border-left-style: var(--tw-border-style);
border-left-width: 12px;
Expand Down Expand Up @@ -470,11 +470,6 @@ exports[`border-r-* 1`] = `
border-right-width: 0;
}
.border-r-123 {
border-right-style: var(--tw-border-style);
border-right-width: 123px;
}
.border-r-2 {
border-right-style: var(--tw-border-style);
border-right-width: 2px;
Expand All @@ -485,6 +480,11 @@ exports[`border-r-* 1`] = `
border-right-width: 4px;
}
.border-r-123 {
border-right-style: var(--tw-border-style);
border-right-width: 123px;
}
.border-r-\\[12px\\] {
border-right-style: var(--tw-border-style);
border-right-width: 12px;
Expand Down Expand Up @@ -583,11 +583,6 @@ exports[`border-s-* 1`] = `
border-inline-start-width: 0;
}
.border-s-123 {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 123px;
}
.border-s-2 {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 2px;
Expand All @@ -598,6 +593,11 @@ exports[`border-s-* 1`] = `
border-inline-start-width: 4px;
}
.border-s-123 {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 123px;
}
.border-s-\\[12px\\] {
border-inline-start-style: var(--tw-border-style);
border-inline-start-width: 12px;
Expand Down Expand Up @@ -696,11 +696,6 @@ exports[`border-t-* 1`] = `
border-top-width: 0;
}
.border-t-123 {
border-top-style: var(--tw-border-style);
border-top-width: 123px;
}
.border-t-2 {
border-top-style: var(--tw-border-style);
border-top-width: 2px;
Expand All @@ -711,6 +706,11 @@ exports[`border-t-* 1`] = `
border-top-width: 4px;
}
.border-t-123 {
border-top-style: var(--tw-border-style);
border-top-width: 123px;
}
.border-t-\\[12px\\] {
border-top-style: var(--tw-border-style);
border-top-width: 12px;
Expand Down Expand Up @@ -813,13 +813,6 @@ exports[`border-x-* 1`] = `
border-right-width: 0;
}
.border-x-123 {
border-left-style: var(--tw-border-style);
border-right-style: var(--tw-border-style);
border-left-width: 123px;
border-right-width: 123px;
}
.border-x-2 {
border-left-style: var(--tw-border-style);
border-right-style: var(--tw-border-style);
Expand All @@ -834,6 +827,13 @@ exports[`border-x-* 1`] = `
border-right-width: 4px;
}
.border-x-123 {
border-left-style: var(--tw-border-style);
border-right-style: var(--tw-border-style);
border-left-width: 123px;
border-right-width: 123px;
}
.border-x-\\[12px\\] {
border-left-style: var(--tw-border-style);
border-right-style: var(--tw-border-style);
Expand Down Expand Up @@ -958,13 +958,6 @@ exports[`border-y-* 1`] = `
border-bottom-width: 0;
}
.border-y-123 {
border-top-style: var(--tw-border-style);
border-bottom-style: var(--tw-border-style);
border-top-width: 123px;
border-bottom-width: 123px;
}
.border-y-2 {
border-top-style: var(--tw-border-style);
border-bottom-style: var(--tw-border-style);
Expand All @@ -979,6 +972,13 @@ exports[`border-y-* 1`] = `
border-bottom-width: 4px;
}
.border-y-123 {
border-top-style: var(--tw-border-style);
border-bottom-style: var(--tw-border-style);
border-top-width: 123px;
border-bottom-width: 123px;
}
.border-y-\\[12px\\] {
border-top-style: var(--tw-border-style);
border-bottom-style: var(--tw-border-style);
Expand Down
3 changes: 2 additions & 1 deletion packages/tailwindcss/src/compile.ts
Expand Up @@ -2,6 +2,7 @@ import { rule, type AstNode, type Rule } from './ast'
import { type Candidate, type Variant } from './candidate'
import { type DesignSystem } from './design-system'
import GLOBAL_PROPERTY_ORDER from './property-order'
import { compare } from './utils/compare'
import { escape } from './utils/escape'
import type { Variants } from './variants'

Expand Down Expand Up @@ -87,7 +88,7 @@ export function compileCandidates(
// Sort by most properties first, then by least properties
zSorting.properties.length - aSorting.properties.length ||
// Sort alphabetically
(aSorting.candidate < zSorting.candidate ? -1 : 1)
compare(aSorting.candidate, zSorting.candidate)
)
})

Expand Down

0 comments on commit cd0c308

Please sign in to comment.