or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-css

CSS parser and stringifier that converts CSS strings to Abstract Syntax Trees and back to CSS strings

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/css@3.0.x

To install, run

npx @tessl/cli install tessl/npm-css@3.0.0

index.mddocs/

CSS

CSS is a comprehensive CSS parser and stringifier for Node.js applications that enables developers to parse CSS strings into Abstract Syntax Trees (AST) and convert AST objects back into CSS strings. It offers robust parsing capabilities with error handling, source map support for debugging and development tools, and flexible stringification options including compression and custom indentation.

Package Information

  • Package Name: css
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install css

Core Imports

const css = require('css');

Individual imports:

const { parse, stringify } = require('css');

Basic Usage

const css = require('css');

// Parse CSS string into AST
const cssString = `
  body {
    background: #eee;
    color: #888;
  }
  
  .header {
    font-size: 24px;
    margin: 10px 0;
  }
`;

const ast = css.parse(cssString, { source: 'styles.css' });

// Convert AST back to CSS string
const formattedCSS = css.stringify(ast);
console.log(formattedCSS);

// Generate compressed CSS
const compressedCSS = css.stringify(ast, { compress: true });

// Generate CSS with source maps
const result = css.stringify(ast, { sourcemap: true });
console.log(result.code); // CSS string
console.log(result.map);  // Source map object

Architecture

The CSS package is built around several key components:

  • Parser Engine: Comprehensive CSS parser that handles all CSS constructs including selectors, declarations, comments, and at-rules
  • AST Structure: Complete Abstract Syntax Tree representation with 15+ node types covering all CSS language features
  • Stringifier System: Flexible output system with Identity (formatted) and Compressed compilers
  • Position Tracking: Detailed source position information for debugging and error reporting
  • Source Map Support: Full source map generation and consumption capabilities
  • Error Handling: Robust error reporting with detailed position information and silent parsing mode

Capabilities

CSS Parsing

Parses CSS strings into detailed Abstract Syntax Trees with comprehensive error handling and position tracking.

/**
 * Parse CSS string into Abstract Syntax Tree
 * @param css - CSS string to parse
 * @param options - Parsing options
 * @returns AST object representing the parsed CSS
 */
function parse(css, options);

interface ParseOptions {
  /** Silently fail on parse errors, collect them in parsingErrors array */
  silent?: boolean;
  /** Path to file containing CSS for better error messages and source maps */
  source?: string;
}

interface StylesheetAST {
  type: 'stylesheet';
  stylesheet: {
    /** Source filename from options.source */
    source?: string;
    /** Array of rules, comments, and at-rules */
    rules: Array<Rule | Comment | AtRule>;
    /** Array of parse errors when silent: true */
    parsingErrors: Error[];
  };
}

CSS Stringification

Converts AST objects back to CSS strings with flexible formatting options and source map support.

/**
 * Convert AST object back to CSS string
 * @param ast - AST object (as produced by css.parse)
 * @param options - Stringification options
 * @returns CSS string or object with code and source map
 */
function stringify(ast, options);

interface StringifyOptions {
  /** Indentation string, defaults to two spaces */
  indent?: string;
  /** Omit comments and extraneous whitespace */
  compress?: boolean;
  /** Generate source map; 'generator' returns SourceMapGenerator object */
  sourcemap?: boolean | 'generator';
  /** Read input source maps (enabled by default) */
  inputSourcemaps?: boolean;
}

interface StringifyResult {
  /** Generated CSS string */
  code: string;
  /** Source map object or SourceMapGenerator */
  map: object | SourceMapGenerator;
}

Error Handling

Enhanced error objects with detailed position information for debugging and development tools.

interface CSSError extends Error {
  /** Full error message with source position */
  message: string;
  /** Error message without position */
  reason: string;
  /** Value from options.source or undefined */
  filename?: string;
  /** Line number (1-based) */
  line: number;
  /** Column number (1-based) */
  column: number;
  /** Full source CSS string */
  source: string;
}

Position Information

Source location tracking for all AST nodes enabling precise debugging and development tool integration.

interface Position {
  /** Starting position */
  start: {
    line: number;
    column: number;
  };
  /** Ending position */
  end: {
    line: number;
    column: number;
  };
  /** Source filename */
  source?: string;
  /** Full source CSS string (shared via prototype) */
  content: string;
}

AST Node Types

Core Node Structure

All AST nodes share common properties and follow a consistent structure.

interface BaseNode {
  /** Node type identifier */
  type: string;
  /** Source position information */
  position?: Position;
  /** Parent node reference (non-enumerable property) */
  parent?: BaseNode | null;
}

Stylesheet

Root node returned by css.parse containing all top-level rules and metadata.

interface Stylesheet extends BaseNode {
  type: 'stylesheet';
  stylesheet: {
    /** Source filename */
    source?: string;
    /** Array of child rules, comments, and at-rules */
    rules: Array<Rule | Comment | AtRule>;
    /** Parse errors when silent mode is enabled */
    parsingErrors: CSSError[];
  };
}

Rule

CSS rule with selectors and declarations (e.g., .header { color: red; }).

interface Rule extends BaseNode {
  type: 'rule';
  /** Array of selectors split on commas, trimmed */
  selectors: string[];
  /** Array of declarations and comments */
  declarations: Array<Declaration | Comment>;
}

Declaration

CSS property declaration (e.g., color: red).

interface Declaration extends BaseNode {
  type: 'declaration';
  /** Property name, trimmed, comments removed */
  property: string;
  /** Property value, trimmed, comments removed */
  value: string;
}

Comment

CSS comment node preserving comment content.

interface Comment extends BaseNode {
  type: 'comment';
  /** Comment content between /* and */ */
  comment: string;
}

At-Rules

Media

@media at-rule for responsive styles.

interface Media extends BaseNode {
  type: 'media';
  /** Media query conditions */
  media: string;
  /** Nested rules, comments, and at-rules */
  rules: Array<Rule | Comment | AtRule>;
}

Keyframes

@keyframes at-rule for CSS animations with vendor prefix support.

interface Keyframes extends BaseNode {
  type: 'keyframes';
  /** Animation name */
  name: string;
  /** Vendor prefix (webkit, moz, etc.) or undefined */
  vendor?: string;
  /** Array of keyframe and comment nodes */
  keyframes: Array<Keyframe | Comment>;
}

interface Keyframe extends BaseNode {
  type: 'keyframe';
  /** Keyframe selectors (0%, 100%, from, to, etc.) */
  values: string[];
  /** Array of declarations and comments */
  declarations: Array<Declaration | Comment>;
}

Import

@import at-rule for importing external stylesheets.

interface Import extends BaseNode {
  type: 'import';
  /** Import statement value */
  import: string;
}

Charset

@charset at-rule for character encoding.

interface Charset extends BaseNode {
  type: 'charset';
  /** Character set value */
  charset: string;
}

Namespace

@namespace at-rule for XML namespace declarations.

interface Namespace extends BaseNode {
  type: 'namespace';
  /** Namespace declaration value */
  namespace: string;
}

Supports

@supports at-rule for feature queries.

interface Supports extends BaseNode {
  type: 'supports';
  /** Feature query conditions */
  supports: string;
  /** Nested rules, comments, and at-rules */
  rules: Array<Rule | Comment | AtRule>;
}

Document

@document at-rule with vendor prefix support.

interface Document extends BaseNode {
  type: 'document';
  /** Document function value */
  document: string;
  /** Vendor prefix or undefined */
  vendor?: string;
  /** Nested rules, comments, and at-rules */
  rules: Array<Rule | Comment | AtRule>;
}

Page

@page at-rule for print styles.

interface Page extends BaseNode {
  type: 'page';
  /** Page selectors */
  selectors: string[];
  /** Array of declarations and comments */
  declarations: Array<Declaration | Comment>;
}

Font-Face

@font-face at-rule for custom font declarations.

interface FontFace extends BaseNode {
  type: 'font-face';
  /** Array of declarations and comments */
  declarations: Array<Declaration | Comment>;
}

Host

@host at-rule for Shadow DOM styling.

interface Host extends BaseNode {
  type: 'host';
  /** Nested rules, comments, and at-rules */
  rules: Array<Rule | Comment | AtRule>;
}

Custom-Media

@custom-media at-rule for custom media queries.

interface CustomMedia extends BaseNode {
  type: 'custom-media';
  /** Custom media name (--prefixed) */
  name: string;
  /** Media query definition */
  media: string;
}

Usage Examples

Basic Parsing and Stringification

const css = require('css');

const stylesheet = `
  .container {
    max-width: 1200px;
    margin: 0 auto;
  }
  
  @media (max-width: 768px) {
    .container {
      max-width: 100%;
      padding: 0 20px;
    }
  }
`;

// Parse with source tracking
const ast = css.parse(stylesheet, { source: 'layout.css' });

// Access parsed data
console.log(ast.stylesheet.rules.length); // Number of top-level rules
console.log(ast.stylesheet.rules[0].selectors); // ['.container']
console.log(ast.stylesheet.rules[0].declarations[0].property); // 'max-width'

// Convert back to CSS
const output = css.stringify(ast, { indent: '  ' });
console.log(output);

Error Handling

const css = require('css');

const invalidCSS = '.broken { color: #invalid-syntax';

try {
  const ast = css.parse(invalidCSS);
} catch (error) {
  console.log(error.reason); // Error message
  console.log(error.line);   // Line number
  console.log(error.column); // Column number
  console.log(error.source); // Full source CSS string
}

// Silent parsing mode
const ast = css.parse(invalidCSS, { silent: true });
console.log(ast.stylesheet.parsingErrors); // Array of errors

Source Map Generation

const css = require('css');

const stylesheet = `
  body { background: white; }
  .header { color: blue; }
`;

const ast = css.parse(stylesheet, { source: 'input.css' });

// Generate with source map
const result = css.stringify(ast, { 
  sourcemap: true,
  compress: false 
});

console.log(result.code); // Generated CSS
console.log(result.map);  // Source map object

// Access source map generator directly
const withGenerator = css.stringify(ast, { 
  sourcemap: 'generator' 
});
console.log(withGenerator.map.toString()); // Source map JSON

Compressed Output

const css = require('css');

const ast = css.parse(`
  /* Main styles */
  .container {
    max-width: 1200px;
    margin: 0 auto;
  }
  
  /* Responsive */
  @media (max-width: 768px) {
    .container { max-width: 100%; }
  }
`);

// Generate compressed CSS (removes comments and whitespace)
const compressed = css.stringify(ast, { compress: true });
console.log(compressed);
// Output: .container{max-width:1200px;margin:0 auto}@media (max-width: 768px){.container{max-width:100%}}