run() — tailwindcss Function Reference
Architecture documentation for the run() function in index.ts from the tailwindcss codebase.
Entity Profile
Dependency Diagram
graph TD c1db9de2_3654_d42b_b9f2_1c5a0ccbd307["run()"] 74d5e127_e3b7_8e32_662a_dee41c541d2e["eprintln()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 74d5e127_e3b7_8e32_662a_dee41c541d2e 3b23cd0c_5ad0_3277_32b3_47ca9425d608["header()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 3b23cd0c_5ad0_3277_32b3_47ca9425d608 92c23351_d4b7_2db4_5496_013b2f5d8883["isRepoDirty()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 92c23351_d4b7_2db4_5496_013b2f5d8883 98270aaa_96c5_20ee_11bb_e7e96422cda4["error()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 98270aaa_96c5_20ee_11bb_e7e96422cda4 1109e3d3_2f0e_658d_04f7_09e68535d07b["info()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 1109e3d3_2f0e_658d_04f7_09e68535d07b f0667321_097b_1dca_a21c_a0c318a6236a["highlight()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| f0667321_097b_1dca_a21c_a0c318a6236a 4ef7606d_6db1_3d23_3a99_f5d91d921964["installedTailwindVersion()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 4ef7606d_6db1_3d23_3a99_f5d91d921964 f7e10dc0_4702_f1e8_5bee_76a7558d1a0a["expectedTailwindVersion()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| f7e10dc0_4702_f1e8_5bee_76a7558d1a0a 845754ab_207c_0988_5948_8599387b64dc["pkg()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 845754ab_207c_0988_5948_8599387b64dc a47e8296_f774_e7ba_0474_76b3d80ed59b["load()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| a47e8296_f774_e7ba_0474_76b3d80ed59b 91c7b7d7_b75e_448f_492f_b7e96c0ac0c5["isMajor()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| 91c7b7d7_b75e_448f_492f_b7e96c0ac0c5 ac975fa0_6dfb_5b95_d79d_ea10cebf80a5["prepareConfig()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| ac975fa0_6dfb_5b95_d79d_ea10cebf80a5 dc1d7e71_14d1_dd51_5d14_8265f9e59cce["migrateJsConfig()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| dc1d7e71_14d1_dd51_5d14_8265f9e59cce bb8f2b95_65ee_f51b_9ea7_6659657e7e6b["success()"] c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 -->|calls| bb8f2b95_65ee_f51b_9ea7_6659657e7e6b style c1db9de2_3654_d42b_b9f2_1c5a0ccbd307 fill:#6366f1,stroke:#818cf8,color:#fff
Relationship Graph
Source Code
packages/@tailwindcss-upgrade/src/index.ts lines 43–360
async function run() {
let base = process.cwd()
eprintln(header())
eprintln()
let cleanup: (() => void)[] = []
if (!flags['--force']) {
// Require a clean git directory
if (isRepoDirty()) {
error('Git directory is not clean. Please stash or commit your changes before migrating.')
info(
`You may use the ${highlight('--force')} flag to silence this warning and perform the migration.`,
)
process.exit(1)
}
}
info(`Upgrading from Tailwind CSS ${highlight(`v${version.installedTailwindVersion(base)}`)}`, {
prefix: '↳ ',
})
if (version.installedTailwindVersion(base) !== version.expectedTailwindVersion(base)) {
let pkgManager = await pkg(base).manager()
error(
[
'Version mismatch',
'',
pc.dim('```diff'),
`${pc.red('-')} ${`${pc.dim('"tailwindcss":')} ${`${pc.dim('"')}${pc.blue(version.expectedTailwindVersion(base))}${pc.dim('"')}`}`} (expected version in ${highlight('package.json')})`,
`${pc.green('+')} ${`${pc.dim('"tailwindcss":')} ${`${pc.dim('"')}${pc.blue(version.installedTailwindVersion(base))}${pc.dim('"')}`}`} (installed version in ${highlight('node_modules')})`,
pc.dim('```'),
'',
`Make sure to run ${highlight(`${pkgManager} install`)} and try again.`,
].join('\n'),
{
prefix: '↳ ',
},
)
process.exit(1)
}
{
// Stylesheet migrations
// Use provided files
let files = flags._.map((file) => path.resolve(base, file))
// Discover CSS files in case no files were provided
if (files.length === 0) {
info('Searching for CSS files in the current directory and its subdirectories…')
files = await globby(['**/*.css'], {
absolute: true,
gitignore: true,
// gitignore: true will first search for all .gitignore including node_modules folders, this makes the initial search much faster
ignore: ['**/node_modules/**'],
})
}
// Ensure we are only dealing with CSS files
files = files.filter((file) => file.endsWith('.css'))
// Analyze the stylesheets
let loadResults = await Promise.allSettled(files.map((filepath) => Stylesheet.load(filepath)))
// Load and parse all stylesheets
for (let result of loadResults) {
if (result.status === 'rejected') {
error(`${result.reason?.message ?? result.reason}`, { prefix: '↳ ' })
}
}
let stylesheets = loadResults
.filter((result) => result.status === 'fulfilled')
.map((result) => result.value)
let originals = new Map(stylesheets.map((sheet) => [sheet, sheet.root.toString()]))
// Analyze the stylesheets
try {
await analyzeStylesheets(stylesheets)
} catch (e: any) {
error(`${e?.message ?? e}`, { prefix: '↳ ' })
}
// Ensure stylesheets are linked to configs. But this is only necessary when
// migrating from v3 to v4.
if (version.isMajor(3)) {
try {
await linkConfigsToStylesheets(stylesheets, {
configPath: flags['--config'],
base,
})
} catch (e: any) {
error(`${e?.message ?? e}`, { prefix: '↳ ' })
}
}
// Migrate js config files, linked to stylesheets
if (stylesheets.some((sheet) => sheet.isTailwindRoot && sheet.linkedConfigPath)) {
info('Migrating JavaScript configuration files…')
}
let configBySheet = new Map<Stylesheet, Awaited<ReturnType<typeof prepareConfig>>>()
let jsConfigMigrationBySheet = new Map<
Stylesheet,
Awaited<ReturnType<typeof migrateJsConfig>>
>()
for (let sheet of stylesheets) {
if (!sheet.isTailwindRoot) continue
if (!version.isMajor(3) && !sheet.linkedConfigPath) continue
let config = await prepareConfig(sheet.linkedConfigPath, { base })
configBySheet.set(sheet, config)
let jsConfigMigration = await migrateJsConfig(
config.designSystem,
config.configFilePath,
base,
)
jsConfigMigrationBySheet.set(sheet, jsConfigMigration)
if (jsConfigMigration !== null) {
// Remove the JS config if it was fully migrated
cleanup.push(() => fs.rm(config.configFilePath))
}
if (jsConfigMigration !== null) {
success(
`Migrated configuration file: ${highlight(relative(config.configFilePath, base))}`,
{ prefix: '↳ ' },
)
}
}
// Migrate each CSS file
if (stylesheets.length > 0) {
info('Migrating stylesheets…')
}
await Promise.all(
stylesheets.map(async (sheet) => {
try {
let config = configBySheet.get(sheet)
let jsConfigMigration = jsConfigMigrationBySheet.get(sheet) ?? null
if (!config) {
for (let parent of sheet.ancestors()) {
if (parent.isTailwindRoot) {
config ??= configBySheet.get(parent)!
jsConfigMigration ??= jsConfigMigrationBySheet.get(parent) ?? null
break
}
}
}
await migrateStylesheet(sheet, {
newPrefix: config?.newPrefix ?? null,
designSystem: config?.designSystem ?? (await sheet.designSystem()),
userConfig: config?.userConfig ?? null,
configFilePath: config?.configFilePath ?? null,
jsConfigMigration,
})
} catch (e: any) {
error(`${e?.message ?? e} in ${highlight(relative(sheet.file!, base))}`, { prefix: '↳ ' })
}
}),
)
// Split up stylesheets (as needed)
if (version.isMajor(3)) {
try {
await splitStylesheets(stylesheets)
} catch (e: any) {
error(`${e?.message ?? e}`, { prefix: '↳ ' })
}
// Cleanup `@import "…" layer(utilities)`
for (let sheet of stylesheets) {
for (let importRule of sheet.importRules) {
if (!importRule.raws.tailwind_injected_layer) continue
let importedSheet = stylesheets.find(
(sheet) => sheet.id === importRule.raws.tailwind_destination_sheet_id,
)
if (!importedSheet) continue
// Only remove the `layer(…)` next to the import if any of the children
// contain `@utility`. Otherwise `@utility` will not be top-level.
if (
!importedSheet.containsRule((node) => node.type === 'atrule' && node.name === 'utility')
) {
continue
}
// Make sure to remove the `layer(…)` from the `@import` at-rule
importRule.params = importRule.params.replace(/ layer\([^)]+\)/, '').trim()
}
}
}
// Format nodes
for (let sheet of stylesheets) {
if (originals.get(sheet) === sheet.root.toString()) continue
await postcss([sortBuckets(), formatNodes()]).process(sheet.root!, { from: sheet.file! })
}
// Write all files to disk
for (let sheet of stylesheets) {
if (!sheet.file) continue
await fs.writeFile(sheet.file, sheet.root.toString())
if (sheet.isTailwindRoot) {
success(`Migrated stylesheet: ${highlight(relative(sheet.file, base))}`, { prefix: '↳ ' })
}
}
info('Updating dependencies…')
{
let pkgManager = pkg(base)
let dependencies = [
'tailwindcss',
'@tailwindcss/cli',
'@tailwindcss/postcss',
'@tailwindcss/vite',
'@tailwindcss/node',
'@tailwindcss/oxide',
'prettier-plugin-tailwindcss',
].filter((dependency) => dependency === 'tailwindcss' || pkgManager.has(dependency))
try {
await pkgManager.add(dependencies.map((dependency) => `${dependency}@latest`))
for (let dependency of dependencies) {
success(`Updated package: ${highlight(dependency)}`, { prefix: '↳ ' })
}
} catch {}
}
let tailwindRootStylesheets = stylesheets.filter((sheet) => sheet.isTailwindRoot && sheet.file)
// Migrate source files
if (tailwindRootStylesheets.length > 0) {
info('Migrating templates…')
}
{
let seenFiles = new Set()
// Template migrations
for (let sheet of tailwindRootStylesheets) {
let compiler = await sheet.compiler()
if (!compiler) continue
let designSystem = await sheet.designSystem()
if (!designSystem) continue
// Figure out the source files to migrate
let sources = (() => {
// Disable auto source detection
if (compiler.root === 'none') {
return []
}
// No root specified, use the base directory
if (compiler.root === null) {
return [{ base, pattern: '**/*', negated: false }]
}
// Use the specified root
return [{ ...compiler.root, negated: false }]
})().concat(compiler.sources)
let config = configBySheet.get(sheet)
let scanner = new Scanner({ sources })
let filesToMigrate = []
for (let file of scanner.files) {
if (file.endsWith('.css')) continue
if (seenFiles.has(file)) continue
seenFiles.add(file)
filesToMigrate.push(file)
}
// Migrate each file
await Promise.allSettled(
filesToMigrate.map((file) =>
migrateTemplate(designSystem, config?.userConfig ?? null, file),
),
)
if (config?.configFilePath) {
success(
`Migrated templates for configuration file: ${highlight(relative(config.configFilePath, base))}`,
{ prefix: '↳ ' },
)
} else {
success(
`Migrated templates for: ${highlight(relative(sheet.file ?? '<unknown>', base))}`,
{
prefix: '↳ ',
},
)
}
}
}
}
if (version.isMajor(3)) {
// PostCSS config migration
await migratePostCSSConfig(base)
}
// Run all cleanup functions because we completed the migration
await Promise.allSettled(cleanup.map((fn) => fn()))
// Figure out if we made any changes
if (isRepoDirty()) {
success('Verify the changes and commit them to your repository.')
} else {
success('No changes were made to your repository.')
}
}
Domain
Subdomains
Calls
Source
Frequently Asked Questions
What does run() do?
run() is a function in the tailwindcss codebase.
What does run() call?
run() calls 22 function(s): ancestors, compiler, containsRule, designSystem, eprintln, error, expectedTailwindVersion, formatNodes, and 14 more.
Analyze Your Own Codebase
Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.
Try Supermodel Free