Home / Function/ linkConfigs() — tailwindcss Function Reference

linkConfigs() — tailwindcss Function Reference

Architecture documentation for the linkConfigs() function in link.ts from the tailwindcss codebase.

Entity Profile

Dependency Diagram

graph TD
  9dd8f849_c8e1_2210_efce_8cd2e70a472c["linkConfigs()"]
  f0667321_097b_1dca_a21c_a0c318a6236a["highlight()"]
  9dd8f849_c8e1_2210_efce_8cd2e70a472c -->|calls| f0667321_097b_1dca_a21c_a0c318a6236a
  505fd744_81c1_a3d8_bae0_2cbba00f74d3["detectConfigPath()"]
  9dd8f849_c8e1_2210_efce_8cd2e70a472c -->|calls| 505fd744_81c1_a3d8_bae0_2cbba00f74d3
  4cd99e59_ac1e_2a1f_0946_33cc1afd2532["get()"]
  9dd8f849_c8e1_2210_efce_8cd2e70a472c -->|calls| 4cd99e59_ac1e_2a1f_0946_33cc1afd2532
  98270aaa_96c5_20ee_11bb_e7e96422cda4["error()"]
  9dd8f849_c8e1_2210_efce_8cd2e70a472c -->|calls| 98270aaa_96c5_20ee_11bb_e7e96422cda4
  a4d70660_306b_669c_4b1c_828588c6371c["relative()"]
  9dd8f849_c8e1_2210_efce_8cd2e70a472c -->|calls| a4d70660_306b_669c_4b1c_828588c6371c
  bb8f2b95_65ee_f51b_9ea7_6659657e7e6b["success()"]
  9dd8f849_c8e1_2210_efce_8cd2e70a472c -->|calls| bb8f2b95_65ee_f51b_9ea7_6659657e7e6b
  style 9dd8f849_c8e1_2210_efce_8cd2e70a472c fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

packages/@tailwindcss-upgrade/src/codemods/css/link.ts lines 9–122

export async function linkConfigs(
  stylesheets: Stylesheet[],
  { configPath, base }: { configPath: string | null; base: string },
) {
  let rootStylesheets = stylesheets.filter((sheet) => sheet.isTailwindRoot)
  if (rootStylesheets.length === 0) {
    throw new Error(
      `Cannot find any CSS files that reference Tailwind CSS.\nBefore your project can be upgraded you need to create a CSS file that imports Tailwind CSS or uses ${highlight('@tailwind')}.`,
    )
  }
  let withoutAtConfig = rootStylesheets.filter((sheet) => {
    let hasConfig = false
    sheet.root.walkAtRules('config', (node) => {
      let configPath = path.resolve(path.dirname(sheet.file!), node.params.slice(1, -1))
      sheet.linkedConfigPath = configPath
      hasConfig = true
      return false
    })
    return !hasConfig
  })

  // All stylesheets have a `@config` directives
  if (withoutAtConfig.length === 0) return

  // Find the config file path for each stylesheet
  let configPathBySheet = new Map<Stylesheet, string>()
  let sheetByConfigPath = new DefaultMap<string, Set<Stylesheet>>(() => new Set())
  for (let sheet of withoutAtConfig) {
    if (!sheet.file) continue

    let localConfigPath = configPath as string
    if (configPath === null) {
      localConfigPath = await detectConfigPath(path.dirname(sheet.file), base)
    } else if (!path.isAbsolute(localConfigPath)) {
      localConfigPath = path.resolve(base, localConfigPath)
    }

    configPathBySheet.set(sheet, localConfigPath)
    sheetByConfigPath.get(localConfigPath).add(sheet)
  }

  let problematicStylesheets = new Set<Stylesheet>()
  for (let sheets of sheetByConfigPath.values()) {
    if (sheets.size > 1) {
      for (let sheet of sheets) {
        problematicStylesheets.add(sheet)
      }
    }
  }

  // There are multiple "root" files without `@config` directives. Manual
  // intervention is needed to link to the correct Tailwind config files.
  if (problematicStylesheets.size > 1) {
    for (let sheet of problematicStylesheets) {
      error(
        `Could not determine configuration file for: ${highlight(relative(sheet.file!, base))}\nUpdate your stylesheet to use ${highlight('@config')} to specify the correct configuration file explicitly and then run the upgrade tool again.`,
        { prefix: '↳ ' },
      )
    }

    process.exit(1)
  }

  let relativePath = relative
  for (let [sheet, configPath] of configPathBySheet) {
    try {
      if (!sheet || !sheet.file) return
      success(
        `Linked ${highlight(relativePath(configPath, base))} to ${highlight(relativePath(sheet.file, base))}`,
        { prefix: '↳ ' },
      )

      // Link the `@config` directive to the root stylesheets

      // Track the config file path on the stylesheet itself for easy access
      // without traversing the CSS ast and finding the corresponding
      // `@config` later.
      sheet.linkedConfigPath = configPath

      // Create a relative path from the current file to the config file.
      let relative = path.relative(path.dirname(sheet.file), configPath)

      // If the path points to a file in the same directory, `path.relative` will
      // remove the leading `./` and we need to add it back in order to still
      // consider the path relative
      if (!relative.startsWith('.') && !path.isAbsolute(relative)) {
        relative = './' + relative
      }

      relative = normalizePath(relative)

      // Add the `@config` directive to the root stylesheet.
      {
        let target = sheet.root as postcss.Root | postcss.AtRule
        let atConfig = postcss.atRule({ name: 'config', params: `'${relative}'` })

        sheet.root.walkAtRules((node) => {
          if (node.name === 'tailwind' || node.name === 'import') {
            target = node
          }
        })

        if (target.type === 'root') {
          sheet.root.prepend(atConfig)
        } else if (target.type === 'atrule') {
          target.after(atConfig)
        }
      }
    } catch (e: any) {
      error('Could not load the configuration file: ' + e.message, { prefix: '↳ ' })
      process.exit(1)
    }
  }
}

Domain

Subdomains

Frequently Asked Questions

What does linkConfigs() do?
linkConfigs() is a function in the tailwindcss codebase.
What does linkConfigs() call?
linkConfigs() calls 6 function(s): detectConfigPath, error, get, highlight, relative, success.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free