Home / Function/ run() — tailwindcss Function Reference

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.')
  }
}

Subdomains

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