or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-processing.mdcompilation.mdindex.mdplugin-development.mdtheme-system.md

ast-processing.mddocs/

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

```