import fs from 'node:fs/promises'
import path from 'node:path'
import type { Config } from 'tailwindcss'
import type { DesignSystem } from '../../../tailwindcss/src/design-system'
import { extractRawCandidates, replaceCandidateInContent } from './candidates'
import { automaticVarInjection } from './codemods/automatic-var-injection'
import { bgGradient } from './codemods/bg-gradient'
import { important } from './codemods/important'
import { prefix } from './codemods/prefix'
export type Migration = (
designSystem: DesignSystem,
userConfig: Config,
rawCandidate: string,
) => string
export default async function migrateContents(
designSystem: DesignSystem,
userConfig: Config,
contents: string,
migrations: Migration[] = [prefix, important, automaticVarInjection, bgGradient],
): Promise<string> {
let candidates = await extractRawCandidates(contents)
candidates.sort((a, z) => z.start - a.start)
let output = contents
for (let { rawCandidate, start, end } of candidates) {
let needsMigration = false
for (let migration of migrations) {
let candidate = migration(designSystem, userConfig, rawCandidate)
if (rawCandidate !== candidate) {
rawCandidate = candidate
needsMigration = true
}
}
if (needsMigration) {
output = replaceCandidateInContent(output, rawCandidate, start, end)
}
}
return output
}
export async function migrate(designSystem: DesignSystem, userConfig: Config, file: string) {
let fullPath = path.resolve(process.cwd(), file)
let contents = await fs.readFile(fullPath, 'utf-8')
await fs.writeFile(fullPath, await migrateContents(designSystem, userConfig, contents))
}