Repository: tailwindlabs/tailwindcss
File: packages/@tailwindcss-upgrade/src/template/candidates.test.ts (TypeScript)

Code before:

  // Keep spaces in strings
  ['content-["hello_world"]', 'content-["hello_world"]'],
  ['content-[____"hello_world"___]', 'content-["hello_world"]'],
]

const variants = [
  ['', ''], // no variant
  ['*:', '*:'],
  ['focus:', 'focus:'],
  ['group-focus:', 'group-focus:'],

  ['hover:focus:', 'hover:focus:'],
  ['hover:group-focus:', 'hover:group-focus:'],
  ['group-hover:focus:', 'group-hover:focus:'],
  ['group-hover:group-focus:', 'group-hover:group-focus:'],

  ['min-[10px]:', 'min-[10px]:'],

  // Normalize spaces
  ['min-[calc(1000px_+_12em)]:', 'min-[calc(1000px+12em)]:'],
  ['min-[calc(1000px_+12em)]:', 'min-[calc(1000px+12em)]:'],
  ['min-[calc(1000px+_12em)]:', 'min-[calc(1000px+12em)]:'],
  ['min-[calc(1000px___+___12em)]:', 'min-[calc(1000px+12em)]:'],

  ['peer-[&_p]:', 'peer-[&_p]:'],
  ['peer-[&_p]:hover:', 'peer-[&_p]:hover:'],
  ['hover:peer-[&_p]:', 'hover:peer-[&_p]:'],
  ['hover:peer-[&_p]:focus:', 'hover:peer-[&_p]:focus:'],
  ['peer-[&:hover]:peer-[&_p]:', 'peer-[&:hover]:peer-[&_p]:'],

  ['[p]:', '[p]:'],
  ['[_p_]:', '[p]:'],
  ['has-[p]:', 'has-[p]:'],
  ['has-[_p_]:', 'has-[p]:'],

  // Simplify `&:is(p)` to `p`
  ['[&:is(p)]:', '[p]:'],
  ['[&:is(_p_)]:', '[p]:'],
  ['has-[&:is(p)]:', 'has-[p]:'],
  ['has-[&:is(_p_)]:', 'has-[p]:'],
]

let combinations: [string, string][] = []

for (let [inputVariant, outputVariant] of variants) {
  for (let [inputCandidate, outputCandidate] of candidates) {
    combinations.push([`${inputVariant}${inputCandidate}`, `${outputVariant}${outputCandidate}`])
  }
}


Review comment (suggestion):
It looks like we're missing tests for the cases where it is unsafe to remove the spaces (I don't know what these are off the top of my head but I know they exist).

Can we figure out what those cases are and make sure we handle them properly? Or do they actually not exist and CSS is just stupid for not letting us omit these stupid spaces? 😄

Code after:
  ['w-1/2', 'w-1/2'],
  ['p-[calc((100vw-theme(maxWidth.2xl))_/_2)]', 'p-[calc((100vw-theme(maxWidth.2xl))/2)]'],

  // Keep spaces in strings
  ['content-["hello_world"]', 'content-["hello_world"]'],
  ['content-[____"hello_world"___]', 'content-["hello_world"]'],
]

const variants = [
  ['', ''], // no variant
  ['*:', '*:'],
  ['focus:', 'focus:'],
  ['group-focus:', 'group-focus:'],

  ['hover:focus:', 'hover:focus:'],
  ['hover:group-focus:', 'hover:group-focus:'],
  ['group-hover:focus:', 'group-hover:focus:'],
  ['group-hover:group-focus:', 'group-hover:group-focus:'],

  ['min-[10px]:', 'min-[10px]:'],

  // Normalize spaces
  ['min-[calc(1000px_+_12em)]:', 'min-[calc(1000px+12em)]:'],
  ['min-[calc(1000px_+12em)]:', 'min-[calc(1000px+12em)]:'],
  ['min-[calc(1000px+_12em)]:', 'min-[calc(1000px+12em)]:'],
  ['min-[calc(1000px___+___12em)]:', 'min-[calc(1000px+12em)]:'],

  ['peer-[&_p]:', 'peer-[&_p]:'],
  ['peer-[&_p]:hover:', 'peer-[&_p]:hover:'],
  ['hover:peer-[&_p]:', 'hover:peer-[&_p]:'],
  ['hover:peer-[&_p]:focus:', 'hover:peer-[&_p]:focus:'],
  ['peer-[&:hover]:peer-[&_p]:', 'peer-[&:hover]:peer-[&_p]:'],

  ['[p]:', '[p]:'],
  ['[_p_]:', '[p]:'],
  ['has-[p]:', 'has-[p]:'],
  ['has-[_p_]:', 'has-[p]:'],

  // Simplify `&:is(p)` to `p`
  ['[&:is(p)]:', '[p]:'],
  ['[&:is(_p_)]:', '[p]:'],
  ['has-[&:is(p)]:', 'has-[p]:'],
  ['has-[&:is(_p_)]:', 'has-[p]:'],
]

let combinations: [string, string][] = []

for (let [inputVariant, outputVariant] of variants) {
  for (let [inputCandidate, outputCandidate] of candidates) {
    combinations.push([`${inputVariant}${inputCandidate}`, `${outputVariant}${outputCandidate}`])
  }