Home / Function/ parse() — tailwindcss Function Reference

parse() — tailwindcss Function Reference

Architecture documentation for the parse() function in value-parser.ts from the tailwindcss codebase.

Entity Profile

Dependency Diagram

graph TD
  0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a["parse()"]
  0e91912d_5423_6991_60b0_8afbca30e459["migrateTheme()"]
  0e91912d_5423_6991_60b0_8afbca30e459 -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  22885c03_eded_5619_af73_329b957dad5a["migrateImport()"]
  22885c03_eded_5619_af73_329b957dad5a -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  a3f66598_fbf6_c4e3_9350_55626482e7b1["migratePreflight()"]
  a3f66598_fbf6_c4e3_9350_55626482e7b1 -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  93d0cdce_24aa_be83_c138_90437551952e["substituteFunctionsInValue()"]
  93d0cdce_24aa_be83_c138_90437551952e -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  5a669ddb_c6e4_576f_e97a_a8046c2834d8["injectVar()"]
  5a669ddb_c6e4_576f_e97a_a8046c2834d8 -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  da84d4b5_fc28_e826_1855_2340e6df074e["createConverter()"]
  da84d4b5_fc28_e826_1855_2340e6df074e -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  360848c5_bd2e_d4dd_ad1b_074434129232["substituteFunctionsInValue()"]
  360848c5_bd2e_d4dd_ad1b_074434129232 -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  c155249e_9c85_fd4e_2707_8f98f0ab5228["printArbitraryValueCache()"]
  c155249e_9c85_fd4e_2707_8f98f0ab5228 -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  38287293_0aa0_94c9_7fb7_8a8a4fa1e9c2["simplifyArbitraryVariantCache()"]
  38287293_0aa0_94c9_7fb7_8a8a4fa1e9c2 -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  b54dff20_77fb_c682_7230_b26aca2e8a48["isVarCache()"]
  b54dff20_77fb_c682_7230_b26aca2e8a48 -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  9df707f7_aef8_37b0_5f90_edacde047f5b["constantFoldDeclaration()"]
  9df707f7_aef8_37b0_5f90_edacde047f5b -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  552e707a_ccba_b2a6_5917_15f7a417896b["theme()"]
  552e707a_ccba_b2a6_5917_15f7a417896b -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  89ce828b_eda4_0d96_a1db_69d4d7bec86b["substituteFunctionsInValue()"]
  89ce828b_eda4_0d96_a1db_69d4d7bec86b -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  5c9381d6_815c_d899_eaab_849d755be47e["createCssUtility()"]
  5c9381d6_815c_d899_eaab_849d755be47e -->|calls| 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a
  style 0638028e_f2f7_8e77_2f19_1bd2ce4b2d6a fill:#6366f1,stroke:#818cf8,color:#fff

Relationship Graph

Source Code

packages/tailwindcss/src/value-parser.ts lines 73–279

export function parse(input: string) {
  input = input.replaceAll('\r\n', '\n')

  let ast: ValueAstNode[] = []

  let stack: (ValueFunctionNode | null)[] = []

  let parent = null as ValueFunctionNode | null

  let buffer = ''

  let peekChar

  for (let i = 0; i < input.length; i++) {
    let currentChar = input.charCodeAt(i)

    switch (currentChar) {
      // Current character is a `\` therefore the next character is escaped,
      // consume it together with the next character and continue.
      case BACKSLASH: {
        buffer += input[i] + input[i + 1]
        i++
        break
      }

      // Typically for math operators, they have to have spaces around them. But
      // there are situations in `theme(colors.red.500/10)` where we use `/`
      // without spaces. Let's make sure this is a separate word as well.
      case SLASH: {
        // 1. Handle everything before the separator as a word
        // Handle everything before the closing paren as a word
        if (buffer.length > 0) {
          let node = word(buffer)
          if (parent) {
            parent.nodes.push(node)
          } else {
            ast.push(node)
          }
          buffer = ''
        }

        // 2. Track the `/` as a word on its own
        let node = word(input[i])
        if (parent) {
          parent.nodes.push(node)
        } else {
          ast.push(node)
        }

        break
      }

      // Space and commas are bundled into separators
      //
      // E.g.:
      //
      // ```css
      // foo(bar, baz)
      //        ^^
      // ```
      case COLON:
      case COMMA:
      case EQUALS:
      case GREATER_THAN:
      case LESS_THAN:
      case NEWLINE:
      case SPACE:
      case TAB: {
        // 1. Handle everything before the separator as a word
        // Handle everything before the closing paren as a word
        if (buffer.length > 0) {
          let node = word(buffer)
          if (parent) {
            parent.nodes.push(node)
          } else {
            ast.push(node)
          }
          buffer = ''
        }

        // 2. Look ahead and find the end of the separator
        let start = i
        let end = i + 1
        for (; end < input.length; end++) {
          peekChar = input.charCodeAt(end)
          if (
            peekChar !== COLON &&
            peekChar !== COMMA &&
            peekChar !== EQUALS &&
            peekChar !== GREATER_THAN &&
            peekChar !== LESS_THAN &&
            peekChar !== NEWLINE &&
            peekChar !== SPACE &&
            peekChar !== TAB
          ) {
            break
          }
        }
        i = end - 1

        let node = separator(input.slice(start, end))
        if (parent) {
          parent.nodes.push(node)
        } else {
          ast.push(node)
        }

        break
      }

      // Start of a string.
      case SINGLE_QUOTE:
      case DOUBLE_QUOTE: {
        let start = i

        // We need to ensure that the closing quote is the same as the opening
        // quote.
        //
        // E.g.:
        //
        // ```css
        // "This is a string with a 'quote' in it"
        //                          ^     ^         -> These are not the end of the string.
        // ```
        for (let j = i + 1; j < input.length; j++) {
          peekChar = input.charCodeAt(j)
          // Current character is a `\` therefore the next character is escaped.
          if (peekChar === BACKSLASH) {
            j += 1
          }

          // End of the string.
          else if (peekChar === currentChar) {
            i = j
            break
          }
        }

        // Adjust `buffer` to include the string.
        buffer += input.slice(start, i + 1)
        break
      }

      // Start of a function call.
      //
      // E.g.:
      //
      // ```css
      // foo(bar, baz)
      //    ^
      // ```
      case OPEN_PAREN: {
        let node = fun(buffer, [])
        buffer = ''

        if (parent) {
          parent.nodes.push(node)
        } else {
          ast.push(node)
        }
        stack.push(node)
        parent = node

        break
      }

      // End of a function call.
      //
      // E.g.:
      //
      // ```css
      // foo(bar, baz)
      //             ^
      // ```
      case CLOSE_PAREN: {
        let tail = stack.pop()

        // Handle everything before the closing paren a word
        if (buffer.length > 0) {
          let node = word(buffer)
          tail?.nodes.push(node)
          buffer = ''
        }

        if (stack.length > 0) {
          parent = stack[stack.length - 1]
        } else {
          parent = null
        }

        break
      }

      // Everything else will be collected in the buffer
      default: {
        buffer += String.fromCharCode(currentChar)
      }
    }
  }

  // Collect the remainder as a word
  if (buffer.length > 0) {
    ast.push(word(buffer))
  }

  return ast
}

Subdomains

Frequently Asked Questions

What does parse() do?
parse() is a function in the tailwindcss codebase.
What does parse() call?
parse() calls 3 function(s): fun, separator, word.
What calls parse()?
parse() is called by 17 function(s): constantFoldDeclaration, createConverter, createCssUtility, decodeArbitraryValue, extractUsedVariables, injectVar, isVarCache, migrateImport, and 9 more.

Analyze Your Own Codebase

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

Try Supermodel Free