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
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8["run()"]
  7e7bbd31_9c12_c2fc_967b_9d88835f6e71["eprintln()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 7e7bbd31_9c12_c2fc_967b_9d88835f6e71
  0e220b58_5412_f8b0_16d3_cedf60b8e3d4["header()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 0e220b58_5412_f8b0_16d3_cedf60b8e3d4
  23bc2bd8_47ba_4456_61d1_528eee3082ed["isRepoDirty()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 23bc2bd8_47ba_4456_61d1_528eee3082ed
  aad2b44f_7d63_9c23_fd06_f010fcd02b2b["error()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| aad2b44f_7d63_9c23_fd06_f010fcd02b2b
  98289381_3219_727d_fea6_371f55963ac8["info()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 98289381_3219_727d_fea6_371f55963ac8
  c1e4d14f_eec6_482b_9f78_0242ee9d41b8["highlight()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| c1e4d14f_eec6_482b_9f78_0242ee9d41b8
  8bd4dbc1_11f3_9e65_a4ee_8c02ed00114e["installedTailwindVersion()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 8bd4dbc1_11f3_9e65_a4ee_8c02ed00114e
  51ca2891_b673_2250_9038_11f53e557699["expectedTailwindVersion()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 51ca2891_b673_2250_9038_11f53e557699
  00cccf76_743c_3b0f_179f_c3f05c433097["pkg()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 00cccf76_743c_3b0f_179f_c3f05c433097
  db944bd6_65e8_1ab3_5a4b_e4e204ebde75["load()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| db944bd6_65e8_1ab3_5a4b_e4e204ebde75
  db7731f5_f3e0_5e90_b5d1_de4eda8ce9d2["isMajor()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| db7731f5_f3e0_5e90_b5d1_de4eda8ce9d2
  d1aa21a8_ad44_6ad5_f1e9_8c1f02bbff2d["prepareConfig()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| d1aa21a8_ad44_6ad5_f1e9_8c1f02bbff2d
  8d0812d4_61e4_e939_916d_a33e94faf43f["migrateJsConfig()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| 8d0812d4_61e4_e939_916d_a33e94faf43f
  d3757426_3d9a_0d83_2369_bcd1fe94ac5f["success()"]
  eb8ababf_fa35_08e1_76f8_c2b2cea868b8 -->|calls| d3757426_3d9a_0d83_2369_bcd1fe94ac5f
  style eb8ababf_fa35_08e1_76f8_c2b2cea868b8 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

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