Skip to content

Commit 457e9b5

Browse files
committed
improve signature generation for variants
1 parent fe5d717 commit 457e9b5

1 file changed

Lines changed: 49 additions & 2 deletions

File tree

packages/@tailwindcss-upgrade/src/codemods/template/signatures.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,17 +224,64 @@ export const computeVariantSignature = new DefaultMap<
224224

225225
// Canonicalize selectors to their minimal form
226226
walk(ast, (node) => {
227+
// At-rules
227228
if (node.kind === 'at-rule' && node.params.includes(' ')) {
228229
node.params = node.params.replaceAll(' ', '')
229-
} else if (node.kind === 'rule') {
230+
}
231+
232+
// Style rules
233+
else if (node.kind === 'rule') {
230234
let selectorAst = SelectorParser.parse(node.selector)
231235
let changed = false
232-
SelectorParser.walk(selectorAst, (node) => {
236+
SelectorParser.walk(selectorAst, (node, { replaceWith }) => {
233237
if (node.kind === 'separator' && node.value !== ' ') {
234238
node.value = node.value.trim()
235239
changed = true
236240
}
241+
242+
// Remove unnecessary `:is(…)` selectors
243+
else if (node.kind === 'function' && node.value === ':is') {
244+
// A single selector inside of `:is(…)` can be replaced with the
245+
// selector itself.
246+
//
247+
// E.g.: `:is(.foo)` → `.foo`
248+
if (node.nodes.length === 1) {
249+
changed = true
250+
replaceWith(node.nodes)
251+
}
252+
253+
// A selector with the universal selector `*` followed by a pseudo
254+
// class, can be replaced with the pseudo class itself.
255+
else if (
256+
node.nodes.length === 2 &&
257+
node.nodes[0].kind === 'selector' &&
258+
node.nodes[0].value === '*' &&
259+
node.nodes[1].kind === 'selector' &&
260+
node.nodes[1].value[0] === ':'
261+
) {
262+
changed = true
263+
replaceWith(node.nodes[1])
264+
}
265+
}
266+
267+
// Ensure `*` exists before pseudo selectors inside of `:not(…)`,
268+
// `:where(…)`, …
269+
//
270+
// E.g.:
271+
//
272+
// `:not(:first-child)` → `:not(*:first-child)`
273+
//
274+
else if (
275+
node.kind === 'function' &&
276+
node.value[0] === ':' &&
277+
node.nodes[0]?.kind === 'selector' &&
278+
node.nodes[0]?.value[0] === ':'
279+
) {
280+
changed = true
281+
node.nodes.unshift({ kind: 'selector', value: '*' })
282+
}
237283
})
284+
238285
if (changed) {
239286
node.selector = SelectorParser.toCss(selectorAst)
240287
}

0 commit comments

Comments
 (0)