Repository: tailwindlabs/tailwindcss
File: packages/tailwindcss/src/ast.ts (TypeScript)

Code before:
    let node = ast[i]
    let path = [...parentPath, node]
    let parent = parentPath.at(-1) ?? null

    if (node.kind === 'rule' || node.kind === 'at-rule') {
      walkDepth(node.nodes, visit, path, context)
    } else if (node.kind === 'context') {
      walkDepth(node.nodes, visit, parentPath, { ...context, ...node.context })
      continue
    }

    visit(node, {
      parent,
      context,
      path,
      replaceWith(newNode) {
        ast.splice(i, 1, ...newNode)

        // Skip over the newly inserted nodes (being depth-first it doesn't make sense to visit them)
        i += newNode.length - 1
      },
    })
  }
}

export function toCss(ast: AstNode[], { printUtilitiesNode = false } = {}) {
  let atRoots: string = ''
  let seenAtProperties = new Set<string>()
  let propertyFallbacksRoot: Declaration[] = []
  let propertyFallbacksUniversal: Declaration[] = []

  function stringify(node: AstNode, depth = 0): string {
    let css = ''
    let indent = '  '.repeat(depth)

    // Rule
    if (node.kind === 'rule') {
      css += `${indent}${node.selector} {\n`
      for (let child of node.nodes) {
        css += stringify(child, depth + 1)
      }
      css += `${indent}}\n`
    }

    // AtRule
    else if (node.kind === 'at-rule') {
      if (
        !printUtilitiesNode &&
        node.name === '@tailwind' &&
        (node.params === 'utilities' || node.params.startsWith('utilities'))
      ) {

Review comment (refactor):
Still feel conflicted about this. Like we talked, this should ultimately not be a concern of the printer (the printer should be agnostic to Tailwind, really). 

Maybe one other idea is that we allow the call sites where we want the `@tailwind utilities` directives to be removed to _mutate_ the `at-rule` with something like `params = ''` or so and then use that as hint to not print it? 

So basically right before [this line](https://github.com/tailwindlabs/tailwindcss/blob/next/packages/tailwindcss/src/index.ts#L509) we do something like this:

```ts
if (utilitiesNode) { 
  // Avoid printing the utility node
  utilitiesNode.name = ''
}
```

Then in the `toCSS` we skip at-rules with `name === ''`. Since the `at-rule` always contains the prefixed `@` this is really not valid otherwise anyways. WDYT?

It would feel good that this concern is documented closer to where we need this than in the CSS AST I think

Code after:
    let node = ast[i]
    let path = [...parentPath, node]
    let parent = parentPath.at(-1) ?? null

    if (node.kind === 'rule' || node.kind === 'at-rule') {
      walkDepth(node.nodes, visit, path, context)
    } else if (node.kind === 'context') {
      walkDepth(node.nodes, visit, parentPath, { ...context, ...node.context })
      continue
    }

    visit(node, {
      parent,
      context,
      path,
      replaceWith(newNode) {
        ast.splice(i, 1, ...newNode)

        // Skip over the newly inserted nodes (being depth-first it doesn't make sense to visit them)
        i += newNode.length - 1
      },
    })
  }
}

export function toCss(ast: AstNode[]) {
  let atRoots: string = ''
  let seenAtProperties = new Set<string>()
  let propertyFallbacksRoot: Declaration[] = []
  let propertyFallbacksUniversal: Declaration[] = []

  function stringify(node: AstNode, depth = 0): string {
    let css = ''
    let indent = '  '.repeat(depth)

    // Rule
    if (node.kind === 'rule') {
      css += `${indent}${node.selector} {\n`
      for (let child of node.nodes) {
        css += stringify(child, depth + 1)
      }
      css += `${indent}}\n`
    }

    // AtRule
    else if (node.kind === 'at-rule') {
      // Print at-rules without nodes with a `;` instead of an empty block.
      //
      // E.g.:
      //
      // ```css