Skip to content

Commit 63537aa

Browse files
authored
Implement getClassOrder instead of sortClassList (#7459)
* implement `getSortOrder` instead of `sortClassList` * rename `getSortOrder` to `getClassOrder` * update changelog
1 parent be5d5c9 commit 63537aa

File tree

3 files changed

+51
-21
lines changed

3 files changed

+51
-21
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
- Remove opacity variables from `:visited` pseudo class ([#7458](https://github.com/tailwindlabs/tailwindcss/pull/7458))
1313
- Support arbitrary values + calc + theme with quotes ([#7462](https://github.com/tailwindlabs/tailwindcss/pull/7462))
1414
- Don't duplicate layer output when scanning content with variants + wildcards ([#7478](https://github.com/tailwindlabs/tailwindcss/pull/7478))
15+
- Implement `getClassOrder` instead of `sortClassList` ([#7459](https://github.com/tailwindlabs/tailwindcss/pull/7459))
1516

1617
## [3.0.22] - 2022-02-11
1718

src/lib/setupContextUtils.js

+11-19
Original file line numberDiff line numberDiff line change
@@ -744,33 +744,25 @@ function registerPlugins(plugins, context) {
744744
// sorting could be weird since you still require them in order to make the
745745
// host utitlies work properly. (Thanks Biology)
746746
let parasiteUtilities = new Set([prefix(context, 'group'), prefix(context, 'peer')])
747-
context.sortClassList = function sortClassList(classes) {
747+
context.getClassOrder = function getClassOrder(classes) {
748748
let sortedClassNames = new Map()
749749
for (let [sort, rule] of generateRules(new Set(classes), context)) {
750750
if (sortedClassNames.has(rule.raws.tailwind.candidate)) continue
751751
sortedClassNames.set(rule.raws.tailwind.candidate, sort)
752752
}
753753

754-
return classes
755-
.map((className) => {
756-
let order = sortedClassNames.get(className) ?? null
754+
return classes.map((className) => {
755+
let order = sortedClassNames.get(className) ?? null
757756

758-
if (order === null && parasiteUtilities.has(className)) {
759-
// This will make sure that it is at the very beginning of the
760-
// `components` layer which technically means 'before any
761-
// components'.
762-
order = context.layerOrder.components
763-
}
757+
if (order === null && parasiteUtilities.has(className)) {
758+
// This will make sure that it is at the very beginning of the
759+
// `components` layer which technically means 'before any
760+
// components'.
761+
order = context.layerOrder.components
762+
}
764763

765-
return [className, order]
766-
})
767-
.sort(([, a], [, z]) => {
768-
if (a === z) return 0
769-
if (a === null) return -1
770-
if (z === null) return 1
771-
return bigSign(a - z)
772-
})
773-
.map(([className]) => className)
764+
return [className, order]
765+
})
774766
}
775767

776768
// Generate a list of strings for autocompletion purposes, e.g.

tests/sortClassList.test.js tests/getSortOrder.test.js

+39-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,42 @@
11
import resolveConfig from '../src/public/resolve-config'
22
import { createContext } from '../src/lib/setupContextUtils'
3+
import bigSign from '../src/util/bigSign'
4+
5+
/**
6+
* This is a function that the prettier-plugin-tailwindcss would use. It would
7+
* do the actual sorting based on the classes and order we return from `getClassOrder`.
8+
*
9+
* This way the actual sorting logic is done in the plugin which allows you to
10+
* put unknown classes at the end for example.
11+
*
12+
* @param {Array<[string, bigint]>} arrayOfTuples
13+
* @returns {string}
14+
*/
15+
function defaultSort(arrayOfTuples) {
16+
return arrayOfTuples
17+
.sort(([, a], [, z]) => {
18+
if (a === z) return 0
19+
if (a === null) return -1
20+
if (z === null) return 1
21+
return bigSign(a - z)
22+
})
23+
.map(([className]) => className)
24+
.join(' ')
25+
}
26+
27+
it('should return a list of tuples with the sort order', () => {
28+
let input = 'font-bold underline hover:font-medium unknown'
29+
let config = {}
30+
let context = createContext(resolveConfig(config))
31+
expect(context.getClassOrder(input.split(' '))).toEqual([
32+
['font-bold', expect.any(BigInt)],
33+
['underline', expect.any(BigInt)],
34+
['hover:font-medium', expect.any(BigInt)],
35+
36+
// Unknown values receive `null`
37+
['unknown', null],
38+
])
39+
})
340

441
it.each([
542
// Utitlies
@@ -33,7 +70,7 @@ it.each([
3370
])('should sort "%s" based on the order we generate them in to "%s"', (input, output) => {
3471
let config = {}
3572
let context = createContext(resolveConfig(config))
36-
expect(context.sortClassList(input.split(' ')).join(' ')).toEqual(output)
73+
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
3774
})
3875

3976
it.each([
@@ -73,6 +110,6 @@ it.each([
73110
(input, output) => {
74111
let config = { prefix: 'tw-' }
75112
let context = createContext(resolveConfig(config))
76-
expect(context.sortClassList(input.split(' ')).join(' ')).toEqual(output)
113+
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
77114
}
78115
)

0 commit comments

Comments
 (0)