or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdcore-formatting.mddocument-builders.mdfile-analysis.mdindex.mdplugin-development.mdutilities.md

document-builders.mddocs/

0

# Document Builder API

1

2

The Document Builder API provides low-level primitives for creating custom formatters and Prettier plugins. It offers a composable system for building formatted output through document objects that represent formatting decisions.

3

4

## Core Concepts

5

6

The Document Builder API uses an intermediate representation called "Doc" objects that describe how code should be formatted. These documents are then printed to strings with line breaking, indentation, and spacing applied.

7

8

### Importing Document Builders

9

```javascript { .api }

10

import { doc } from 'prettier';

11

12

// Access builder functions

13

const { builders, printer, utils } = doc;

14

15

// Or import specific builders

16

import { doc } from 'prettier';

17

const { group, line, indent, join } = doc.builders;

18

```

19

20

## Document Builder Functions

21

22

### Basic Building Blocks

23

24

### join

25

```javascript { .api }

26

function join(separator: Doc, docs: Doc[]): Doc

27

```

28

29

Join an array of documents with a separator document between each element.

30

31

**Parameters:**

32

- `separator` (Doc): Document to insert between elements

33

- `docs` (Doc[]): Array of documents to join

34

35

**Example:**

36

```javascript { .api }

37

const params = ['a', 'b', 'c'];

38

const joined = doc.builders.join(

39

[',', doc.builders.line],

40

params

41

);

42

// Result: 'a,\nb,\nc' (when broken) or 'a, b, c' (when flat)

43

```

44

45

### Line Breaking Documents

46

47

### line

48

```javascript { .api }

49

const line: Doc

50

```

51

52

A line break that becomes a space when the parent group fits on one line.

53

54

**Example:**

55

```javascript { .api }

56

const statement = doc.builders.group([

57

'if (',

58

'condition',

59

')',

60

doc.builders.line,

61

'doSomething();'

62

]);

63

// Result: 'if (condition) doSomething();' or 'if (condition)\ndoSomething();'

64

```

65

66

### softline

67

```javascript { .api }

68

const softline: Doc

69

```

70

71

A line break that becomes nothing (empty string) when the parent group fits on one line.

72

73

**Example:**

74

```javascript { .api }

75

const array = doc.builders.group([

76

'[',

77

doc.builders.softline,

78

doc.builders.join([',', doc.builders.line], elements),

79

doc.builders.softline,

80

']'

81

]);

82

// Result: '[a, b, c]' or '[\n a,\n b,\n c\n]'

83

```

84

85

### hardline

86

```javascript { .api }

87

const hardline: Doc

88

```

89

90

An unconditional line break that always creates a new line.

91

92

**Example:**

93

```javascript { .api }

94

const statements = [

95

'const a = 1;',

96

'const b = 2;'

97

];

98

const program = doc.builders.join(doc.builders.hardline, statements);

99

// Result: 'const a = 1;\nconst b = 2;'

100

```

101

102

### literalline

103

```javascript { .api }

104

const literalline: Doc

105

```

106

107

A line break that preserves literal newlines without triggering parent group breaking.

108

109

### hardlineWithoutBreakParent

110

```javascript { .api }

111

const hardlineWithoutBreakParent: Doc

112

```

113

114

An unconditional line break that doesn't trigger parent group breaking.

115

116

### literallineWithoutBreakParent

117

```javascript { .api }

118

const literallineWithoutBreakParent: Doc

119

```

120

121

A literal line break that doesn't trigger parent group breaking.

122

123

### Grouping and Layout

124

125

### group

126

```javascript { .api }

127

function group(doc: Doc, options?: { shouldBreak?: boolean, id?: symbol }): Doc

128

```

129

130

Group documents that should be formatted consistently - either all on one line or all broken across multiple lines.

131

132

**Parameters:**

133

- `doc` (Doc): Document to group

134

- `options` (optional): Grouping options

135

- `shouldBreak` (boolean): Force group to break

136

- `id` (symbol): Unique identifier for the group

137

138

**Example:**

139

```javascript { .api }

140

const functionCall = doc.builders.group([

141

'functionName(',

142

doc.builders.indent([

143

doc.builders.softline,

144

doc.builders.join([',', doc.builders.line], args)

145

]),

146

doc.builders.softline,

147

')'

148

]);

149

// Result: 'functionName(a, b, c)' or 'functionName(\n a,\n b,\n c\n)'

150

```

151

152

### conditionalGroup

153

```javascript { .api }

154

function conditionalGroup(docs: Doc[], options?: { shouldBreak?: boolean }): Doc

155

```

156

157

Try multiple document variants in order, using the first one that fits.

158

159

**Example:**

160

```javascript { .api }

161

const alternatives = doc.builders.conditionalGroup([

162

// Try inline first

163

['(', doc.builders.join(', ', args), ')'],

164

// Fall back to multi-line

165

[

166

'(',

167

doc.builders.indent([doc.builders.line, doc.builders.join([',', doc.builders.line], args)]),

168

doc.builders.line,

169

')'

170

]

171

]);

172

```

173

174

### fill

175

```javascript { .api }

176

function fill(docs: Doc[]): Doc

177

```

178

179

Fill available line space optimally by trying to fit as many documents as possible on each line.

180

181

**Example:**

182

```javascript { .api }

183

const words = ['This', 'is', 'a', 'long', 'sentence', 'that', 'should', 'wrap'];

184

const paragraph = doc.builders.fill(

185

doc.builders.join(doc.builders.line, words)

186

);

187

// Result: Wraps words to fit available width

188

```

189

190

### Indentation and Alignment

191

192

### indent

193

```javascript { .api }

194

function indent(doc: Doc): Doc

195

```

196

197

Increase indentation level for the contained document.

198

199

**Example:**

200

```javascript { .api }

201

const block = [

202

'{',

203

doc.builders.indent([

204

doc.builders.hardline,

205

'statement1;',

206

doc.builders.hardline,

207

'statement2;'

208

]),

209

doc.builders.hardline,

210

'}'

211

];

212

// Result: '{\n statement1;\n statement2;\n}'

213

```

214

215

### indentIfBreak

216

```javascript { .api }

217

function indentIfBreak(doc: Doc, options?: { groupId?: symbol }): Doc

218

```

219

220

Conditionally indent the document only if the parent group breaks.

221

222

**Parameters:**

223

- `doc` (Doc): Document to conditionally indent

224

- `options` (object, optional): Options including group ID for specific targeting

225

226

**Example:**

227

```javascript { .api }

228

const conditional = doc.builders.group([

229

'if (',

230

doc.builders.indentIfBreak([

231

doc.builders.line,

232

'longCondition'

233

]),

234

doc.builders.line,

235

')'

236

]);

237

// Indents only when the group breaks

238

```

239

240

### align

241

```javascript { .api }

242

function align(n: number | string, doc: Doc): Doc

243

```

244

245

Align document to a specific column offset.

246

247

**Parameters:**

248

- `n` (number | string): Spaces to align (number) or alignment string

249

- `doc` (Doc): Document to align

250

251

**Example:**

252

```javascript { .api }

253

const aligned = doc.builders.align(4, [

254

'let x = longVariableName +',

255

doc.builders.line,

256

'anotherLongVariableName;'

257

]);

258

// Result: Aligns continuation line to column 4

259

```

260

261

### addAlignmentToDoc

262

```javascript { .api }

263

function addAlignmentToDoc(doc: Doc, size: number, tabWidth: number): Doc

264

```

265

266

Add additional alignment space to an existing document.

267

268

**Parameters:**

269

- `doc` (Doc): Document to add alignment to

270

- `size` (number): Number of spaces to add for alignment

271

- `tabWidth` (number): Tab width for calculating proper alignment

272

273

**Example:**

274

```javascript { .api }

275

const withAlignment = doc.builders.addAlignmentToDoc(

276

existingDoc,

277

4,

278

2

279

);

280

// Adds 4 spaces of alignment considering tab width

281

```

282

283

### dedent

284

```javascript { .api }

285

function dedent(doc: Doc): Doc

286

```

287

288

Decrease indentation level for the contained document.

289

290

### dedentToRoot

291

```javascript { .api }

292

function dedentToRoot(doc: Doc): Doc

293

```

294

295

Remove all indentation, aligning to the root level.

296

297

### markAsRoot

298

```javascript { .api }

299

function markAsRoot(doc: Doc): Doc

300

```

301

302

Mark document as root for indentation calculations.

303

304

### Conditional Formatting

305

306

### ifBreak

307

```javascript { .api }

308

function ifBreak(breakContents: Doc, flatContents?: Doc, options?: { groupId?: symbol }): Doc

309

```

310

311

Conditionally include content based on whether the parent group breaks.

312

313

**Parameters:**

314

- `breakContents` (Doc): Content when parent group breaks

315

- `flatContents` (Doc, optional): Content when parent group is flat

316

- `options` (optional): Options including group ID to check

317

318

**Example:**

319

```javascript { .api }

320

const arrayElements = doc.builders.group([

321

'[',

322

doc.builders.indent([

323

doc.builders.softline,

324

doc.builders.join([

325

',',

326

doc.builders.ifBreak(doc.builders.hardline, doc.builders.line)

327

], elements)

328

]),

329

doc.builders.softline,

330

']'

331

]);

332

```

333

334

### Line Manipulation

335

336

### lineSuffix

337

```javascript { .api }

338

function lineSuffix(doc: Doc): Doc

339

```

340

341

Content that should appear at the end of the current line.

342

343

**Example:**

344

```javascript { .api }

345

const statement = [

346

'const x = value;',

347

doc.builders.lineSuffix(' // comment')

348

];

349

// Result: 'const x = value; // comment'

350

```

351

352

### lineSuffixBoundary

353

```javascript { .api }

354

const lineSuffixBoundary: Doc

355

```

356

357

Boundary marker for line suffix content placement.

358

359

### Special Documents

360

361

### cursor

362

```javascript { .api }

363

const cursor: Doc

364

```

365

366

Placeholder for cursor position in editor integrations.

367

368

### breakParent

369

```javascript { .api }

370

const breakParent: Doc

371

```

372

373

Force the parent group to break across multiple lines.

374

375

**Example:**

376

```javascript { .api }

377

const forceBreak = doc.builders.group([

378

'items: [',

379

doc.builders.indent([

380

doc.builders.line,

381

'item1,',

382

doc.builders.breakParent, // Forces parent group to break

383

doc.builders.line,

384

'item2'

385

]),

386

doc.builders.line,

387

']'

388

]);

389

```

390

391

### trim

392

```javascript { .api }

393

const trim: Doc

394

```

395

396

Remove trailing whitespace from the current line.

397

398

### label

399

```javascript { .api }

400

function label(label: string, doc: Doc): Doc

401

```

402

403

Label document for debugging and development purposes.

404

405

## Document Printer

406

407

### printDocToString

408

```javascript { .api }

409

function printDocToString(doc: Doc, options: PrintOptions): PrintResult

410

```

411

412

Convert a document to a formatted string with the specified print options.

413

414

**Types:**

415

```javascript { .api }

416

interface PrintOptions {

417

printWidth?: number; // Maximum line width (default: 80)

418

tabWidth?: number; // Tab width (default: 2)

419

useTabs?: boolean; // Use tabs for indentation (default: false)

420

endOfLine?: 'auto' | 'lf' | 'crlf' | 'cr'; // Line ending style

421

}

422

423

interface PrintResult {

424

formatted: string; // Formatted output

425

cursorOffset: number; // Cursor position (if cursor doc was used)

426

}

427

```

428

429

**Example:**

430

```javascript { .api }

431

const document = doc.builders.group([

432

'function(',

433

doc.builders.indent([

434

doc.builders.softline,

435

doc.builders.join([',', doc.builders.line], parameters)

436

]),

437

doc.builders.softline,

438

')'

439

]);

440

441

const result = doc.printer.printDocToString(document, {

442

printWidth: 80,

443

tabWidth: 2,

444

useTabs: false

445

});

446

447

console.log(result.formatted);

448

```

449

450

## Document Utilities

451

452

### traverseDoc

453

```javascript { .api }

454

function traverseDoc(

455

doc: Doc,

456

onEnter?: (doc: Doc) => void | boolean | Doc,

457

onExit?: (doc: Doc) => void,

458

shouldTraverseConditionalGroup?: boolean

459

): void

460

```

461

462

Traverse document tree with enter/exit callbacks.

463

464

### findInDoc

465

```javascript { .api }

466

function findInDoc(doc: Doc, fn: (doc: Doc) => boolean, defaultValue?: any): any

467

```

468

469

Find element in document tree matching predicate function.

470

471

### mapDoc

472

```javascript { .api }

473

function mapDoc(doc: Doc, fn: (doc: Doc) => Doc): Doc

474

```

475

476

Transform document tree by applying function to each node.

477

478

### willBreak

479

```javascript { .api }

480

function willBreak(doc: Doc): boolean

481

```

482

483

Check if document will cause parent group to break.

484

485

### canBreak

486

```javascript { .api }

487

function canBreak(doc: Doc): boolean

488

```

489

490

Check if document can break across lines.

491

492

### removeLines

493

```javascript { .api }

494

function removeLines(doc: Doc): Doc

495

```

496

497

Remove all line breaks from document.

498

499

### stripTrailingHardline

500

```javascript { .api }

501

function stripTrailingHardline(doc: Doc): Doc

502

```

503

504

Remove trailing hard line breaks from document.

505

506

### replaceEndOfLine

507

```javascript { .api }

508

function replaceEndOfLine(doc: Doc, replacement?: Doc): Doc

509

```

510

511

Replace end-of-line characters in document.

512

513

## Usage Patterns

514

515

### Building Complex Layouts

516

```javascript { .api }

517

function formatObjectExpression(properties) {

518

return doc.builders.group([

519

'{',

520

properties.length > 0 ? [

521

doc.builders.indent([

522

doc.builders.line,

523

doc.builders.join([',', doc.builders.line], properties.map(formatProperty))

524

]),

525

doc.builders.line

526

] : '',

527

'}'

528

]);

529

}

530

531

function formatProperty(prop) {

532

return doc.builders.group([

533

prop.key,

534

': ',

535

prop.value

536

]);

537

}

538

```

539

540

### Plugin Development

541

```javascript { .api }

542

// Example plugin printer function

543

function print(path, options, print) {

544

const node = path.node;

545

546

switch (node.type) {

547

case 'CustomNode':

548

return doc.builders.group([

549

'custom(',

550

doc.builders.indent([

551

doc.builders.softline,

552

doc.builders.join([',', doc.builders.line],

553

node.args.map((_, index) => path.call(print, 'args', index))

554

)

555

]),

556

doc.builders.softline,

557

')'

558

]);

559

560

default:

561

return '';

562

}

563

}

564

```

565

566

### Conditional Formatting

567

```javascript { .api }

568

function formatArray(elements, options) {

569

const shouldBreakElements = elements.length > 3 ||

570

elements.some(el => willBreak(el));

571

572

return doc.builders.group([

573

'[',

574

elements.length > 0 ? [

575

doc.builders.indent([

576

shouldBreakElements ? doc.builders.hardline : doc.builders.softline,

577

doc.builders.join([

578

',',

579

shouldBreakElements ? doc.builders.hardline : doc.builders.line

580

], elements)

581

]),

582

shouldBreakElements ? doc.builders.hardline : doc.builders.softline

583

] : '',

584

']'

585

], { shouldBreak: shouldBreakElements });

586

}

587

```

588

589

## Deprecated Functions

590

591

### concat (Deprecated)

592

```javascript { .api }

593

function concat(parts: Doc[]): Doc[]

594

```

595

596

**⚠️ Deprecated**: This function will be removed in v4. Use array syntax directly instead.

597

598

Legacy function that simply returns the parts array. Modern code should use arrays directly.

599

600

**Example:**

601

```javascript { .api }

602

// Deprecated usage

603

const doc = doc.builders.concat([part1, part2, part3]);

604

605

// Modern equivalent

606

const doc = [part1, part2, part3];

607

```