0
# AST Processing
1
2
Low-level CSS abstract syntax tree processing for advanced use cases and custom tooling. The AST system provides direct access to CSS parsing, manipulation, and generation.
3
4
## Capabilities
5
6
### AST Node Creation
7
8
Functions for creating different types of AST nodes.
9
10
```typescript { .api }
11
/**
12
* Creates a style rule AST node
13
* @param selector - CSS selector string
14
* @param nodes - Child nodes for this rule
15
* @returns StyleRule node
16
*/
17
function styleRule(selector: string, nodes?: AstNode[]): StyleRule;
18
19
/**
20
* Creates an at-rule AST node
21
* @param name - At-rule name (e.g., '@media', '@keyframes')
22
* @param params - At-rule parameters
23
* @param nodes - Child nodes for this rule
24
* @returns AtRule node
25
*/
26
function atRule(name: string, params?: string, nodes?: AstNode[]): AtRule;
27
28
/**
29
* Creates a rule node (auto-detects style rule vs at-rule)
30
* @param selector - CSS selector or at-rule string
31
* @param nodes - Child nodes for this rule
32
* @returns StyleRule or AtRule node
33
*/
34
function rule(selector: string, nodes?: AstNode[]): StyleRule | AtRule;
35
36
/**
37
* Creates a CSS declaration AST node
38
* @param property - CSS property name
39
* @param value - CSS property value
40
* @param important - Whether declaration is !important
41
* @returns Declaration node
42
*/
43
function decl(property: string, value?: string, important?: boolean): Declaration;
44
45
/**
46
* Creates a comment AST node
47
* @param value - Comment text content
48
* @returns Comment node
49
*/
50
function comment(value: string): Comment;
51
52
/**
53
* Creates a context wrapper node
54
* @param context - Context metadata object
55
* @param nodes - Child nodes to wrap
56
* @returns Context node
57
*/
58
function context(context: Record<string, any>, nodes: AstNode[]): Context;
59
60
/**
61
* Creates an at-root wrapper node
62
* @param nodes - Child nodes to hoist to root level
63
* @returns AtRoot node
64
*/
65
function atRoot(nodes: AstNode[]): AtRoot;
66
```
67
68
**Usage Examples:**
69
70
```typescript
71
import { styleRule, atRule, decl, comment, context } from "tailwindcss";
72
73
// Create a simple style rule
74
const buttonRule = styleRule('.btn', [
75
decl('padding', '0.5rem 1rem'),
76
decl('border-radius', '0.25rem'),
77
decl('font-weight', '500'),
78
]);
79
80
// Create a media query
81
const mediaRule = atRule('@media', '(min-width: 768px)', [
82
styleRule('.btn', [
83
decl('padding', '0.75rem 1.5rem'),
84
]),
85
]);
86
87
// Create at-rule with auto-detection
88
const keyframesRule = rule('@keyframes spin', [
89
styleRule('to', [
90
decl('transform', 'rotate(360deg)'),
91
]),
92
]);
93
94
// Add comments and context
95
const ast = [
96
comment('Button component styles'),
97
context({ component: 'button' }, [buttonRule, mediaRule]),
98
];
99
```
100
101
### AST Walking
102
103
Traverse and manipulate AST nodes.
104
105
```typescript { .api }
106
/**
107
* Walk through AST nodes with a callback function
108
* @param ast - Array of AST nodes to traverse
109
* @param callback - Function called for each node
110
*/
111
function walk(
112
ast: AstNode[],
113
callback: (
114
node: AstNode,
115
utils: {
116
parent: AstNode | null;
117
replaceWith: (nodes: AstNode[]) => void;
118
context: Record<string, any>;
119
}
120
) => WalkAction | void
121
): void;
122
123
enum WalkAction {
124
/** Continue walking child nodes */
125
Continue,
126
/** Skip child nodes but continue with siblings */
127
Skip,
128
/** Stop walking entirely */
129
Stop,
130
}
131
```
132
133
**Usage Examples:**
134
135
```typescript
136
import { walk, WalkAction } from "tailwindcss";
137
138
// Find and modify declarations
139
walk(ast, (node, { replaceWith }) => {
140
if (node.kind === 'declaration' && node.property === 'color') {
141
// Replace color declarations with custom property
142
replaceWith([
143
decl('color', 'var(--text-color)', node.important),
144
]);
145
}
146
});
147
148
// Remove comments
149
walk(ast, (node, { replaceWith }) => {
150
if (node.kind === 'comment') {
151
replaceWith([]);
152
}
153
});
154
155
// Skip processing certain rules
156
walk(ast, (node) => {
157
if (node.kind === 'rule' && node.selector.includes('.skip')) {
158
return WalkAction.Skip;
159
}
160
});
161
```
162
163
### CSS Generation
164
165
Convert AST nodes back to CSS strings.
166
167
```typescript { .api }
168
/**
169
* Convert AST nodes to CSS string
170
* @param ast - Array of AST nodes to convert
171
* @param withSourceMaps - Whether to include source map information
172
* @returns Generated CSS string
173
*/
174
function toCss(ast: AstNode[], withSourceMaps?: boolean): string;
175
```
176
177
**Usage Example:**
178
179
```typescript
180
import { toCss, styleRule, decl } from "tailwindcss";
181
182
const ast = [
183
styleRule('.btn', [
184
decl('padding', '0.5rem 1rem'),
185
decl('background-color', '#3b82f6'),
186
decl('color', 'white'),
187
]),
188
];
189
190
const css = toCss(ast);
191
console.log(css);
192
// Output:
193
// .btn {
194
// padding: 0.5rem 1rem;
195
// background-color: #3b82f6;
196
// color: white;
197
// }
198
```
199
200
### AST Optimization
201
202
Optimize AST for better performance and smaller output.
203
204
```typescript { .api }
205
/**
206
* Optimize AST nodes for better performance and output
207
* @param ast - Array of AST nodes to optimize
208
* @param designSystem - Design system for context
209
* @param polyfills - Polyfill configuration
210
* @returns Optimized AST nodes
211
*/
212
function optimizeAst(
213
ast: AstNode[],
214
designSystem: DesignSystem,
215
polyfills?: Polyfills
216
): AstNode[];
217
```
218
219
## AST Node Types
220
221
### StyleRule Node
222
223
Represents CSS style rules with selectors and declarations.
224
225
```typescript { .api }
226
interface StyleRule {
227
kind: 'rule';
228
selector: string;
229
nodes: AstNode[];
230
src?: SourceLocation;
231
dst?: SourceLocation;
232
}
233
```
234
235
### AtRule Node
236
237
Represents CSS at-rules like @media, @keyframes, etc.
238
239
```typescript { .api }
240
interface AtRule {
241
kind: 'at-rule';
242
name: string;
243
params: string;
244
nodes: AstNode[];
245
src?: SourceLocation;
246
dst?: SourceLocation;
247
}
248
```
249
250
### Declaration Node
251
252
Represents CSS property declarations.
253
254
```typescript { .api }
255
interface Declaration {
256
kind: 'declaration';
257
property: string;
258
value: string | undefined;
259
important: boolean;
260
src?: SourceLocation;
261
dst?: SourceLocation;
262
}
263
```
264
265
### Comment Node
266
267
Represents CSS comments.
268
269
```typescript { .api }
270
interface Comment {
271
kind: 'comment';
272
value: string;
273
src?: SourceLocation;
274
dst?: SourceLocation;
275
}
276
```
277
278
### Context Node
279
280
Wrapper node for adding metadata and context to child nodes.
281
282
```typescript { .api }
283
interface Context {
284
kind: 'context';
285
context: Record<string, string | boolean>;
286
nodes: AstNode[];
287
src?: undefined;
288
dst?: undefined;
289
}
290
```
291
292
### AtRoot Node
293
294
Wrapper node for hoisting child nodes to the root level.
295
296
```typescript { .api }
297
interface AtRoot {
298
kind: 'at-root';
299
nodes: AstNode[];
300
src?: undefined;
301
dst?: undefined;
302
}
303
```
304
305
## Source Location
306
307
Source location information for debugging and source maps.
308
309
```typescript { .api }
310
interface SourceLocation {
311
start: { line: number; column: number };
312
end: { line: number; column: number };
313
source?: string;
314
}
315
```
316
317
## Union Types
318
319
```typescript { .api }
320
type Rule = StyleRule | AtRule;
321
type AstNode = StyleRule | AtRule | Declaration | Comment | Context | AtRoot;
322
```
323
324
## Advanced Usage
325
326
### Custom AST Processing
327
328
```typescript
329
import { compileAst, walk, styleRule, decl } from "tailwindcss";
330
331
// Create custom AST
332
const customAst = [
333
styleRule(':root', [
334
decl('--primary', '#3b82f6'),
335
decl('--secondary', '#10b981'),
336
]),
337
styleRule('.custom-btn', [
338
decl('background', 'var(--primary)'),
339
decl('color', 'white'),
340
]),
341
];
342
343
// Process with Tailwind
344
const result = await compileAst(customAst);
345
346
// Generate final CSS
347
const finalAst = result.build(['bg-primary', 'text-white']);
348
```
349
350
### AST Transformation Pipeline
351
352
```typescript
353
import { walk, toCss } from "tailwindcss";
354
355
function transformAst(ast: AstNode[]): AstNode[] {
356
// Step 1: Add vendor prefixes
357
walk(ast, (node, { replaceWith }) => {
358
if (node.kind === 'declaration' && node.property === 'transform') {
359
replaceWith([
360
decl('-webkit-transform', node.value, node.important),
361
decl('-moz-transform', node.value, node.important),
362
decl('transform', node.value, node.important),
363
]);
364
}
365
});
366
367
// Step 2: Minify selectors
368
walk(ast, (node) => {
369
if (node.kind === 'rule') {
370
node.selector = node.selector.replace(/\s+/g, ' ').trim();
371
}
372
});
373
374
return ast;
375
}
376
377
// Use in processing pipeline
378
const processedAst = transformAst(originalAst);
379
const css = toCss(processedAst);
380
```