Home / Function/ canonicalizeAst() — tailwindcss Function Reference

canonicalizeAst() — tailwindcss Function Reference

Architecture documentation for the canonicalizeAst() function in canonicalize-candidates.ts from the tailwindcss codebase.

Function typescript Oxide Extractor calls 6 called by 2

Entity Profile

Dependency Diagram

graph TD
  e559573b_f2f8_833b_27e7_100efea815c0["canonicalizeAst()"]
  f6c14bbb_2e42_58cc_18f1_c89a243da9c0["canonicalize-candidates.ts"]
  e559573b_f2f8_833b_27e7_100efea815c0 -->|defined in| f6c14bbb_2e42_58cc_18f1_c89a243da9c0
  6e657054_f39b_c09e_18b9_3bc9c9e15d42["createUtilitySignatureCache()"]
  6e657054_f39b_c09e_18b9_3bc9c9e15d42 -->|calls| e559573b_f2f8_833b_27e7_100efea815c0
  2fa686dc_af14_1b06_e253_cd3be040c4fd["createUtilityPropertiesCache()"]
  2fa686dc_af14_1b06_e253_cd3be040c4fd -->|calls| e559573b_f2f8_833b_27e7_100efea815c0
  25758157_37c7_6a41_4b05_7fc8c0e52eed["expandDeclaration()"]
  e559573b_f2f8_833b_27e7_100efea815c0 -->|calls| 25758157_37c7_6a41_4b05_7fc8c0e52eed
  7b28cf23_d052_57d9_b076_5abe2b724a3f["resolveVariablesInValue()"]
  e559573b_f2f8_833b_27e7_100efea815c0 -->|calls| 7b28cf23_d052_57d9_b076_5abe2b724a3f
  f875e425_9644_1071_3601_45e7c7f789d3["constantFoldDeclaration()"]
  e559573b_f2f8_833b_27e7_100efea815c0 -->|calls| f875e425_9644_1071_3601_45e7c7f789d3
  49a16f31_6459_6af3_3eaa_e3ee599b3619["printArbitraryValue()"]
  e559573b_f2f8_833b_27e7_100efea815c0 -->|calls| 49a16f31_6459_6af3_3eaa_e3ee599b3619
  e7db6358_7af5_e4b2_792d_749691a304cc["add()"]
  e559573b_f2f8_833b_27e7_100efea815c0 -->|calls| e7db6358_7af5_e4b2_792d_749691a304cc
  4982d9ce_98d4_85d9_44af_7cc47b93c482["walk()"]
  e559573b_f2f8_833b_27e7_100efea815c0 -->|calls| 4982d9ce_98d4_85d9_44af_7cc47b93c482
  style e559573b_f2f8_833b_27e7_100efea815c0 fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

packages/tailwindcss/src/canonicalize-candidates.ts lines 2070–2171

function canonicalizeAst(designSystem: DesignSystem, ast: AstNode[], options: SignatureOptions) {
  let { rem } = options

  walk(ast, {
    enter(node, ctx) {
      // Optimize declarations
      if (node.kind === 'declaration') {
        if (node.value === undefined || node.property === '--tw-sort') {
          return WalkAction.Replace([])
        }

        // Ignore `--tw-{property}` if `{property}` exists with the same value
        if (node.property.startsWith('--tw-')) {
          if (
            (ctx.parent?.nodes ?? []).some(
              (sibling) =>
                sibling.kind === 'declaration' &&
                node.value === sibling.value &&
                node.important === sibling.important &&
                !sibling.property.startsWith('--tw-'),
            )
          ) {
            return WalkAction.Replace([])
          }
        }

        if (options.features & SignatureFeatures.ExpandProperties) {
          let replacement = expandDeclaration(node, options.features)
          if (replacement) return WalkAction.Replace(replacement)
        }

        // Resolve theme values to their inlined value.
        if (node.value.includes('var(')) {
          node.value = resolveVariablesInValue(node.value, designSystem)
        }

        // Very basic `calc(…)` constant folding to handle the spacing scale
        // multiplier:
        //
        // Input:  `--spacing(4)`
        //       → `calc(var(--spacing, 0.25rem) * 4)`
        //       → `calc(0.25rem * 4)`       ← this is the case we will see
        //                                     after inlining the variable
        //       → `1rem`
        node.value = constantFoldDeclaration(node.value, rem)

        // We will normalize the `node.value`, this is the same kind of logic
        // we use when printing arbitrary values. It will remove unnecessary
        // whitespace.
        //
        // Essentially normalizing the `node.value` to a canonical form.
        node.value = printArbitraryValue(node.value)
      }

      // Replace special nodes with its children
      else if (node.kind === 'context' || node.kind === 'at-root') {
        return WalkAction.Replace(node.nodes)
      }

      // Remove comments
      else if (node.kind === 'comment') {
        return WalkAction.Replace([])
      }

      // Remove at-rules that are not needed for the signature
      else if (node.kind === 'at-rule' && node.name === '@property') {
        return WalkAction.Replace([])
      }
    },
    exit(node) {
      if (node.kind === 'rule' || node.kind === 'at-rule') {
        // Remove declarations that are re-defined again later.
        //
        // This could maybe result in unwanted behavior (because similar
        // properties typically exist for backwards compatibility), but for
        // signature purposes we can assume that the last declaration wins.
        if (node.nodes.length > 1) {
          let seen = new Set<string>()
          for (let i = node.nodes.length - 1; i >= 0; i--) {
            let child = node.nodes[i]
            if (child.kind !== 'declaration') continue

Domain

Subdomains

Frequently Asked Questions

What does canonicalizeAst() do?
canonicalizeAst() is a function in the tailwindcss codebase, defined in packages/tailwindcss/src/canonicalize-candidates.ts.
Where is canonicalizeAst() defined?
canonicalizeAst() is defined in packages/tailwindcss/src/canonicalize-candidates.ts at line 2070.
What does canonicalizeAst() call?
canonicalizeAst() calls 6 function(s): add, constantFoldDeclaration, expandDeclaration, printArbitraryValue, resolveVariablesInValue, walk.
What calls canonicalizeAst()?
canonicalizeAst() is called by 2 function(s): createUtilityPropertiesCache, createUtilitySignatureCache.

Analyze Your Own Codebase

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

Try Supermodel Free