CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-css-tree

A tool set for CSS: fast detailed parser (CSS → AST), walker (AST traversal), generator (AST → CSS) and lexer (validation and matching) based on specs and browser implementations

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

data-structures.mddocs/

Data Structures

Specialized data structures including the List class for efficient AST node manipulation and various stream classes for tokenization.

Capabilities

List Class

A doubly-linked list implementation optimized for AST operations with extensive manipulation methods:

/**
 * Doubly-linked list optimized for AST node collections
 */
class List<T> {
  /** Creates an empty list */
  constructor();
  
  /** Number of items in the list */
  readonly size: number;
  /** Whether the list is empty */
  readonly isEmpty: boolean;
  /** First item in the list */
  readonly first: T;
  /** Last item in the list */
  readonly last: T;
}

List Navigation Methods

Methods for traversing and accessing list items:

class List<T> {
  /**
   * Iterate over items from first to last
   * @param fn - Function called for each item
   * @param thisArg - Value to use as 'this' when executing fn
   */
  forEach(fn: (item: T, index: number, list: List<T>) => void, thisArg?: any): void;

  /**
   * Iterate over items from last to first
   * @param fn - Function called for each item
   * @param thisArg - Value to use as 'this' when executing fn
   */
  forEachRight(fn: (item: T, index: number, list: List<T>) => void, thisArg?: any): void;

  /**
   * Reduce list items from first to last
   * @param fn - Reducer function
   * @param initialValue - Initial accumulator value
   * @param thisArg - Value to use as 'this' when executing fn
   */
  reduce<U>(fn: (acc: U, item: T, index: number, list: List<T>) => U, initialValue: U, thisArg?: any): U;

  /**
   * Reduce list items from last to first
   * @param fn - Reducer function
   * @param initialValue - Initial accumulator value
   * @param thisArg - Value to use as 'this' when executing fn
   */
  reduceRight<U>(fn: (acc: U, item: T, index: number, list: List<T>) => U, initialValue: U, thisArg?: any): U;

  /**
   * Test whether at least one item passes the predicate
   * @param fn - Predicate function
   * @param thisArg - Value to use as 'this' when executing fn
   */
  some(fn: (item: T, index: number, list: List<T>) => boolean, thisArg?: any): boolean;
}

List Transformation Methods

Methods for creating new lists with transformed content:

class List<T> {
  /**
   * Create new list with transformed items
   * @param fn - Transformation function
   * @param thisArg - Value to use as 'this' when executing fn
   */
  map<U>(fn: (item: T, index: number, list: List<T>) => U, thisArg?: any): List<U>;

  /**
   * Create new list with filtered items
   * @param fn - Predicate function
   * @param thisArg - Value to use as 'this' when executing fn
   */
  filter(fn: (item: T, index: number, list: List<T>) => boolean, thisArg?: any): List<T>;
}

List Conversion Methods

Methods for converting between List and Array:

class List<T> {
  /**
   * Populate list from array
   * @param array - Array to convert
   */
  fromArray(array: T[]): this;

  /**
   * Convert list to array
   * @returns Array containing all list items
   */
  toArray(): T[];

  /**
   * JSON serialization (same as toArray)
   * @returns Array for JSON serialization
   */
  toJSON(): T[];
}

List Manipulation Methods

Methods for modifying list content:

class List<T> {
  /** Remove all items from the list */
  clear(): void;

  /** Create shallow copy of the list */
  copy(): List<T>;

  /**
   * Add item to the beginning of the list
   * @param item - List item to prepend
   */
  prepend(item: ListItem<T>): this;

  /**
   * Add data to the beginning of the list
   * @param data - Data to prepend
   */
  prependData(data: T): this;

  /**
   * Add item to the end of the list
   * @param item - List item to append
   */
  append(item: ListItem<T>): this;

  /**
   * Add data to the end of the list
   * @param data - Data to append
   */
  appendData(data: T): this;

  /**
   * Insert item at specific position
   * @param item - List item to insert
   * @param before - Item to insert before (null for end)
   */
  insert(item: ListItem<T>, before: ListItem<T> | null): this;

  /**
   * Insert data at specific position
   * @param data - Data to insert
   * @param before - Item to insert before (null for end)
   */
  insertData(data: T, before: ListItem<T> | null): this;

  /**
   * Remove specific item from the list
   * @param item - List item to remove
   * @returns The removed item
   */
  remove(item: ListItem<T>): ListItem<T>;
}

List Convenience Methods

Array-like methods for familiar API:

class List<T> {
  /**
   * Add data to end (alias for appendData)
   * @param data - Data to add
   */
  push(data: T): void;

  /**
   * Remove and return last item
   * @returns Last list item or null
   */
  pop(): ListItem<T> | null;

  /**
   * Add data to beginning (alias for prependData)
   * @param data - Data to add
   */
  unshift(data: T): void;

  /**
   * Remove and return first item
   * @returns First list item or null
   */
  shift(): ListItem<T> | null;
}

Advanced List Operations

Methods for complex list manipulations:

class List<T> {
  /**
   * Prepend entire list to beginning
   * @param list - List to prepend
   */
  prependList(list: List<T>): this;

  /**
   * Append entire list to end
   * @param list - List to append
   */
  appendList(list: List<T>): this;

  /**
   * Insert entire list at position
   * @param list - List to insert
   * @param before - Item to insert before
   */
  insertList(list: List<T>, before: ListItem<T> | null): this;

  /**
   * Replace item with new item or list
   * @param oldItem - Item to replace
   * @param newItemOrList - Replacement item or list
   */
  replace(oldItem: ListItem<T>, newItemOrList: T | List<T>): this;
}

Cursor Navigation Methods

Methods for conditional traversal:

class List<T> {
  /**
   * Iterate forward until condition is met
   * @param start - Starting item
   * @param fn - Function called for each item (return true to stop)
   * @param thisArg - Value to use as 'this' when executing fn
   */
  nextUntil(start: ListItem<T>, fn: (item: T, item: ListItem<T>, list: List<T>) => boolean, thisArg?: any): void;

  /**
   * Iterate backward until condition is met
   * @param start - Starting item
   * @param fn - Function called for each item (return true to stop)
   * @param thisArg - Value to use as 'this' when executing fn
   */
  prevUntil(start: ListItem<T>, fn: (item: T, item: ListItem<T>, list: List<T>) => boolean, thisArg?: any): void;
}

ListItem Interface

Individual list item structure:

interface ListItem<T> {
  /** Previous item in the list */
  prev: ListItem<T> | null;
  /** Next item in the list */
  next: ListItem<T> | null;
  /** The actual data */
  data: T;
}

/**
 * Creates a new list item
 * @param data - Data for the item
 * @returns New list item
 */
List.createItem<T>(data: T): ListItem<T>;

Usage Examples:

import { List } from 'css-tree';

// Create and populate list
const list = new List();
list.appendData('first');
list.appendData('second');
list.appendData('third');

console.log(list.size);     // 3
console.log(list.first);    // 'first'
console.log(list.last);     // 'third'

// Iterate over items
list.forEach((item, index) => {
  console.log(`${index}: ${item}`);
});

// Transform list
const upperList = list.map(item => item.toUpperCase());

// Filter list
const longItems = list.filter(item => item.length > 5);

// Convert to/from array
const array = list.toArray();
const newList = new List().fromArray(['a', 'b', 'c']);

// Advanced manipulation
const item = List.createItem('inserted');
list.insert(item, list.first.next); // Insert after first item

// Remove items conditionally
list.forEach((data, index, list) => {
  if (data === 'second') {
    list.remove(list.getItemAt(index));
  }
});

AST-Specific Usage

How List is used in CSS Tree AST nodes:

import { parse, walk, List } from 'css-tree';

const ast = parse('.a, .b { color: red; margin: 10px; }');

// AST nodes use List for children
walk(ast, (node) => {
  if (node.children && node.children instanceof List) {
    console.log(`${node.type} has ${node.children.size} children`);
    
    // Iterate over child nodes
    node.children.forEach((child, index) => {
      console.log(`  Child ${index}: ${child.type}`);
    });
    
    // Modify children
    if (node.type === 'SelectorList') {
      // Add new selector
      node.children.appendData({
        type: 'Selector',
        children: new List().fromArray([
          { type: 'ClassSelector', name: 'new-class' }
        ])
      });
    }
    
    // Remove children conditionally
    node.children.forEach((child, index, list) => {
      if (child.type === 'WhiteSpace') {
        list.remove(list.getItemAt(index));
      }
    });
  }
});

Performance Characteristics

List performance and optimization considerations:

// Lists are optimized for:
// - Frequent insertions/deletions at any position: O(1)
// - Iteration: O(n)
// - Size access: O(1)

// Arrays are better for:
// - Random access by index: O(1) vs O(n)
// - Memory efficiency for small collections

// Use List.toArray() for index-based operations
function findNodeByIndex(list, index) {
  if (index >= 0 && index < list.size) {
    return list.toArray()[index];
  }
  return null;
}

// Use List methods for structural modifications
function insertNodes(list, nodes, position) {
  const nodeList = new List().fromArray(nodes);
  const targetItem = findItemByIndex(list, position);
  list.insertList(nodeList, targetItem);
}

// Efficient list merging
function mergeLists(...lists) {
  const result = new List();
  lists.forEach(list => {
    if (list instanceof List) {
      result.appendList(list);
    } else if (Array.isArray(list)) {
      result.appendList(new List().fromArray(list));
    }
  });
  return result;
}

Install with Tessl CLI

npx tessl i tessl/npm-css-tree

docs

data-structures.md

generation.md

index.md

parsing.md

tokenization.md

traversal.md

utilities.md

validation.md

tile.json