AST.md 6.3 KB

Abstract Syntax Tree (AST)

Overview

The AST represents CSS as a tree structure where each node has a specific type and properties. All nodes share common properties and have type-specific properties.

Common Properties

All AST nodes have these properties:

type

The node type as a string. See Node Types for all possible values.

position (optional)

Position information for the node in the source code:

{
  start: { line: number; column: number };
  end: { line: number; column: number };
  source?: string;
}

parent (optional)

Reference to the parent node in the AST.

Node Types

stylesheet

The root node representing an entire CSS document.

Properties:

  • stylesheet.source (optional): Source file path
  • stylesheet.rules: Array of top-level rules
  • stylesheet.parsingErrors (optional): Array of parse errors when silent option is used

Example:

{
  "type": "stylesheet",
  "stylesheet": {
    "rules": [
      // ... other nodes
    ]
  }
}

rule

A CSS rule with selectors and declarations.

Properties:

  • selectors: Array of CSS selectors as strings
  • declarations: Array of declarations and comments

Example:

{
  "type": "rule",
  "selectors": ["body", "html"],
  "declarations": [
    {
      "type": "declaration",
      "property": "color",
      "value": "red"
    }
  ]
}

declaration

A CSS property declaration.

Properties:

  • property: The CSS property name
  • value: The CSS property value as a string

Example:

{
  "type": "declaration",
  "property": "background-color",
  "value": "#ffffff"
}

comment

A CSS comment.

Properties:

  • comment: The comment text (without /* and */)

Example:

{
  "type": "comment",
  "comment": " This is a comment "
}

media

A @media rule.

Properties:

  • media: The media query string
  • rules: Array of rules within the media block

Example:

{
  "type": "media",
  "media": "screen and (max-width: 768px)",
  "rules": [
    // ... nested rules
  ]
}

keyframes

A @keyframes rule.

Properties:

  • name: The keyframes name
  • vendor (optional): Vendor prefix (e.g., "-webkit-")
  • keyframes: Array of keyframe rules and comments

Example:

{
  "type": "keyframes",
  "name": "fade",
  "keyframes": [
    {
      "type": "keyframe",
      "values": ["from"],
      "declarations": [
        {
          "type": "declaration",
          "property": "opacity",
          "value": "0"
        }
      ]
    }
  ]
}

keyframe

A keyframe within a @keyframes rule.

Properties:

  • values: Array of keyframe selectors (e.g., ["from"], ["to"], ["50%"])
  • declarations: Array of declarations and comments

import

An @import rule.

Properties:

  • import: The import string (URL or media query)

Example:

{
  "type": "import",
  "import": "url('styles.css')"
}

charset

A @charset rule.

Properties:

  • charset: The character encoding

Example:

{
  "type": "charset",
  "charset": "utf-8"
}

namespace

A @namespace rule.

Properties:

  • namespace: The namespace declaration

Example:

{
  "type": "namespace",
  "namespace": "url(http://www.w3.org/1999/xhtml)"
}

supports

A @supports rule.

Properties:

  • supports: The supports condition
  • rules: Array of rules within the supports block

Example:

{
  "type": "supports",
  "supports": "(display: grid)",
  "rules": [
    // ... nested rules
  ]
}

document

A @document rule.

Properties:

  • document: The document condition
  • vendor (optional): Vendor prefix
  • rules: Array of rules within the document block

page

A @page rule.

Properties:

  • selectors: Array of page selectors
  • declarations: Array of declarations and comments

font-face

A @font-face rule.

Properties:

  • declarations: Array of font declarations and comments

host

A :host rule.

Properties:

  • rules: Array of rules within the host block

container

A @container rule.

Properties:

  • container: The container query
  • rules: Array of rules within the container block

layer

A @layer rule.

Properties:

  • layer: The layer name
  • rules (optional): Array of rules within the layer block

custom-media

A @custom-media rule.

Properties:

  • name: The custom media query name
  • media: The media query definition

starting-style

A @starting-style rule.

Properties:

  • rules: Array of rules within the starting-style block

Type Hierarchy

The AST nodes are organized in the following hierarchy:

  • CssStylesheetAST - Root node
  • CssAtRuleAST - Union of all at-rule and rule nodes
  • CssAllNodesAST - Union of all possible node types

Working with the AST

Traversing Nodes

import { parse, CssStylesheetAST } from '@adobe/css-tools';

const ast: CssStylesheetAST = parse('body { color: red; }');

// Access top-level rules
ast.stylesheet.rules.forEach(rule => {
  if (rule.type === 'rule') {
    console.log('Selectors:', rule.selectors);
    rule.declarations.forEach(decl => {
      if (decl.type === 'declaration') {
        console.log(`${decl.property}: ${decl.value}`);
      }
    });
  }
});

Modifying Nodes

// Add a new declaration
const newDecl = {
  type: 'declaration' as const,
  property: 'font-size',
  value: '16px'
};

// Find a rule and add the declaration
ast.stylesheet.rules.forEach(rule => {
  if (rule.type === 'rule' && rule.selectors.includes('body')) {
    rule.declarations.push(newDecl);
  }
});

Error Handling

When parsing with the silent option, errors are collected in the AST:

const ast = parse('invalid css {', { silent: true });

if (ast.stylesheet.parsingErrors) {
  ast.stylesheet.parsingErrors.forEach(error => {
    console.error('Parse error:', error.message);
  });
}

Position Information

Position information is available on most nodes and includes:

  • start.line and start.column: Beginning of the node
  • end.line and end.column: End of the node
  • source: Source file path (if provided during parsing)

This is useful for:

  • Error reporting
  • Source mapping
  • Code analysis tools
  • IDE integration