Parsing CSS
Package: @lanexio/parser-grammar-css Stable
Layer: 2 (Grammar). Depends only on @lanexio/parser-core.
Runtime: Universal (browser, server, edge worker).
Overview
Section titled “Overview”parseCss implements a CSS Syntax Module Level 3 parser with a two-pass architecture: tokenization (§4) followed by tree construction (§§5/9). It handles qualified rules, at-rules, declarations, functions, blocks, comments, and whitespace — producing a structured AST with Stylesheet, QualifiedRule, AtRule, Declaration, Selector, etc.
Input is always a Uint8Array. Output is always a LexTree. Malformed CSS produces CssKind.Error nodes — parseCss never throws.
The parser passes all 125 CourtBouillon css-parsing-tests cases and preserves comments and whitespace for round-trip fidelity.
Import
Section titled “Import”import { parseCss, CssKind, CSS_KIND_NAMES_BY_ID, cssGrammar, type ParseCssOptions, type CssKindType,} from '@lanexio/parser-grammar-css';Parse a stylesheet
Section titled “Parse a stylesheet”import { parseCss } from '@lanexio/parser-grammar-css';
const encoder = new TextEncoder();const tree = parseCss(encoder.encode('body { color: red; font-size: 16px; }'));
console.log(tree.nodeCount); // total nodesconsole.log(tree.root.kind); // Stylesheet root kind id (0x0900)parseCss accepts a Uint8Array. Always use TextEncoder when converting a string to bytes.
At-rules and nested blocks
Section titled “At-rules and nested blocks”const tree = parseCss(encoder.encode(`@media screen and (min-width: 768px) { .container { max-width: 720px; }}`));// Produces: Stylesheet → AtRule("@media") → Block → QualifiedRule(".container") → ...Comments and whitespace preserved
Section titled “Comments and whitespace preserved”import { parseCss, CssKind } from '@lanexio/parser-grammar-css';
const tree = parseCss(encoder.encode('/* header */\nbody { color: red; }'));
for (const node of tree.root.children()) { if (node.kind === CssKind.Comment) { console.log('comment:', /* extract bytes via node.range */); }}ParseCssOptions
Section titled “ParseCssOptions”ParseCssOptions is an empty record (Record<string, never>). Reserved for future extension.
Detect LexError nodes
Section titled “Detect LexError nodes”import { parseCss, CssKind } from '@lanexio/parser-grammar-css';
const encoder = new TextEncoder();const tree = parseCss(encoder.encode('body { color: }')); // missing value
for (const node of tree.root.children()) { if (node.kind === CssKind.Error) { console.log('parse error at', node.range); }}parseCss never throws. Malformed CSS produces CssKind.Error nodes. The parser always recovers.
CssKind constants
Section titled “CssKind constants”import { CssKind } from '@lanexio/parser-grammar-css';
// CssKind is a const object. Use 'as const' pattern, never enum.const kind: CssKindType = CssKind.Declaration;
// Node kind IDs (0x0900 block)CssKind.Stylesheet; // 0x0900CssKind.QualifiedRule; // 0x0901CssKind.AtRule; // 0x0902CssKind.Declaration; // 0x0903CssKind.Block; // 0x0904CssKind.Function; // 0x0905CssKind.Selector; // 0x0906CssKind.PropertyName; // 0x0907CssKind.Value; // 0x0908CssKind.Comment; // 0x0909CssKind.Whitespace; // 0x090aCssKind.Error; // 0x09ffCssKind values are stable across versions. Never use raw numbers — always reference CssKind.<name>.
Full exports
Section titled “Full exports”| Export | Type | Description |
|---|---|---|
parseCss | (bytes: Uint8Array, options?: ParseCssOptions) => LexTree | Parse CSS Syntax Level 3. Never throws. |
ParseCssOptions | Record<string, never> | Options for parseCss (empty, reserved). |
CssKind | const object | Numeric kind IDs for all CSS node types (0x0900 block). |
CssKindType | type union | Union of all CssKind values. |
CSS_KIND_NAMES_BY_ID | Readonly<Record<number, string>> | Kind-name lookup by numeric ID. |
cssGrammar | Lanexio ParserPureGrammar | Grammar descriptor for parser-pure. |
Conformance
Section titled “Conformance”| Metric | Value |
|---|---|
| CourtBouillon corpus | 125 / 125 (100%) |
| Error cases (not thrown) | 24 |
| verify:no-throw | 54 entry points |
| Bundle | 4,779 / 16,384 B (29.2%) |
| Fuzz soak (300s) | 4.3M rounds / 0 crashes |
Companion packages
Section titled “Companion packages”@lanexio/parser-core— shared buffer protocol,LexTree,LexNode,LexCursor.@lanexio/parser-pure— pure-TypeScript multi-grammar bridge; passcssGrammartocreateParser.@lanexio/parser— unified entry point; importsparseCssas an optional peer dependency.