mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Sort classes using position of first matching rule (#11504)
* Refactor * Sort based on first occurence of a candidate This primarily affects components and utilities which contain multiple matched classes * Simplify * Update changelog * Update
This commit is contained in:
parent
243226887f
commit
80f3e85fa0
@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Ensure `repeating-conic-gradient` is detected as an image ([#11180](https://github.com/tailwindlabs/tailwindcss/pull/11180))
|
||||
- Move unknown pseudo-elements outside of `:is` by default ([#11345](https://github.com/tailwindlabs/tailwindcss/pull/11345))
|
||||
- Escape animation names when prefixes contain special characters ([#11470](https://github.com/tailwindlabs/tailwindcss/pull/11470))
|
||||
- Sort classes using position of first matching rule ([#11504](https://github.com/tailwindlabs/tailwindcss/pull/11504))
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
@ -949,7 +949,11 @@ function registerPlugins(plugins, context) {
|
||||
let idx = BigInt(parasiteUtilities.length)
|
||||
|
||||
for (const [, rule] of rules) {
|
||||
sortedClassNames.set(rule.raws.tailwind.candidate, idx++)
|
||||
let candidate = rule.raws.tailwind.candidate
|
||||
|
||||
// When multiple rules match a candidate
|
||||
// always take the position of the first one
|
||||
sortedClassNames.set(candidate, sortedClassNames.get(candidate) ?? idx++)
|
||||
}
|
||||
|
||||
return classes.map((className) => {
|
||||
|
||||
@ -143,3 +143,41 @@ crosscheck(() => {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('sorts based on first occurence of a candidate / rule', () => {
|
||||
let classes = [
|
||||
['foo-1 foo', 'foo foo-1'],
|
||||
['bar', 'bar'],
|
||||
['foo-1 foo', 'foo foo-1'],
|
||||
]
|
||||
|
||||
let config = {
|
||||
theme: {},
|
||||
plugins: [
|
||||
function ({ addComponents }) {
|
||||
addComponents({
|
||||
'.foo': { display: 'block' },
|
||||
'.foo-1': { display: 'block' },
|
||||
'.bar': { display: 'block' },
|
||||
|
||||
// This rule matches both the candidate `foo` and `bar`
|
||||
// But when sorting `foo` — we've already got a
|
||||
// position for `foo` so we should use it
|
||||
'.bar .foo': { display: 'block' },
|
||||
})
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
// Same context, different class lists
|
||||
let context = createContext(resolveConfig(config))
|
||||
for (const [input, output] of classes) {
|
||||
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
|
||||
}
|
||||
|
||||
// Different context, different class lists
|
||||
for (const [input, output] of classes) {
|
||||
context = createContext(resolveConfig(config))
|
||||
expect(defaultSort(context.getClassOrder(input.split(' ')))).toEqual(output)
|
||||
}
|
||||
})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user