Skip to content

Commit

Permalink
Sort classes using position of first matching rule (#11504)
Browse files Browse the repository at this point in the history
* Refactor

* Sort based on first occurence of a candidate

This primarily affects components and utilities which contain multiple matched classes

* Simplify

* Update changelog

* Update
  • Loading branch information
thecrypticace committed Jul 13, 2023
1 parent 2432268 commit 80f3e85
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
6 changes: 5 additions & 1 deletion src/lib/setupContextUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
38 changes: 38 additions & 0 deletions tests/getSortOrder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
})

0 comments on commit 80f3e85

Please sign in to comment.