Repository: tailwindlabs/tailwindcss
File: packages/@tailwindcss-upgrade/src/migrate-postcss.ts (TypeScript)

Code before:
      await pkg(base).remove(packagesToRemove)
    } catch {}
  }

  success(`↳ PostCSS config has been upgraded.`)
}

async function migratePostCSSJSConfig(configPath: string): Promise<{
  didAddPostcssClient: boolean
  didRemoveAutoprefixer: boolean
  didRemovePostCSSImport: boolean
} | null> {
  function isTailwindCSSPlugin(line: string) {
    return /['"]?tailwindcss['"]?\: ?\{\}/.test(line)
  }
  function isPostCSSImportPlugin(line: string) {
    return /['"]?postcss-import['"]?\: ?\{\}/.test(line)
  }
  function isAutoprefixerPlugin(line: string) {
    return /['"]?autoprefixer['"]?\: ?\{\}/.test(line)
  }
  function isTailwindCSSNestingPlugin(line: string) {
    return /['"]tailwindcss\/nesting['"]\: ?(\{\}|['"]postcss-nesting['"])/.test(line)
  }

  info(`Attempt to upgrade the PostCSS config in file: ${highlight(relative(configPath))}`)

  let isSimpleConfig = await isSimplePostCSSConfig(configPath)
  if (!isSimpleConfig) {
    warn(`The PostCSS config contains dynamic JavaScript and can not be automatically migrated.`)
    return null
  }

  let didAddPostcssClient = false
  let didRemoveAutoprefixer = false
  let didRemovePostCSSImport = false

  let content = await fs.readFile(configPath, 'utf-8')
  let lines = content.split('\n')
  let newLines: string[] = []
  for (let i = 0; i < lines.length; i++) {
    let line = lines[i]

    if (isTailwindCSSPlugin(line)) {
      didAddPostcssClient = true
      newLines.push(line.replace('tailwindcss:', `'@tailwindcss/postcss':`))
    } else if (isAutoprefixerPlugin(line)) {
      didRemoveAutoprefixer = true
    } else if (isPostCSSImportPlugin(line)) {
      // Check that there are no unknown plugins before the tailwindcss plugin
      let hasUnknownPluginsBeforeTailwindCSS = false

Review comment (suggestion):
```suggestion
  info(`Upgrading the PostCSS config in file: ${highlight(relative(configPath))}`)
```

Code after:
      ].filter(Boolean) as string[]
      await pkg(base).remove(packagesToRemove)
      for (let pkg of packagesToRemove) {
        success(`↳ Removed package: ${highlight(pkg)}`)
      }
    } catch {}
  }

  if (didMigrate && jsConfigPath) {
    success(`↳ Migrated PostCSS configuration: ${highlight(relative(jsConfigPath, base))}`)
  }
}

async function migratePostCSSJSConfig(configPath: string): Promise<{
  didAddPostcssClient: boolean
  didRemoveAutoprefixer: boolean
  didRemovePostCSSImport: boolean
} | null> {
  function isTailwindCSSPlugin(line: string) {
    return /['"]?tailwindcss['"]?\: ?\{\}/.test(line)
  }
  function isPostCSSImportPlugin(line: string) {
    return /['"]?postcss-import['"]?\: ?\{\}/.test(line)
  }
  function isAutoprefixerPlugin(line: string) {
    return /['"]?autoprefixer['"]?\: ?\{\}/.test(line)
  }
  function isTailwindCSSNestingPlugin(line: string) {
    return /['"]tailwindcss\/nesting['"]\: ?(\{\}|['"]postcss-nesting['"])/.test(line)
  }

  info('Migrating PostCSS configuration…')

  let isSimpleConfig = await isSimplePostCSSConfig(configPath)
  if (!isSimpleConfig) {
    warn('The PostCSS config contains dynamic JavaScript and can not be automatically migrated.')
    return null
  }

  let didAddPostcssClient = false
  let didRemoveAutoprefixer = false
  let didRemovePostCSSImport = false

  let content = await fs.readFile(configPath, 'utf-8')
  let lines = content.split('\n')
  let newLines: string[] = []
  for (let i = 0; i < lines.length; i++) {
    let line = lines[i]

    if (isTailwindCSSPlugin(line)) {
      didAddPostcssClient = true