or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

error-handling.mdevent-management.mdindex.mdrenderers.mdtask-configuration.mdtask-management.md
tile.json

renderers.mddocs/

0

# Renderers

1

2

Multiple built-in renderers for different environments and use cases, with customizable options, TTY detection, and fallback mechanisms for various output scenarios.

3

4

## Capabilities

5

6

### Renderer Selection

7

8

Configure primary and fallback renderers with automatic selection based on environment conditions.

9

10

```typescript { .api }

11

/**

12

* Valid renderer specification values

13

*/

14

type ListrRendererValue =

15

| 'default'

16

| 'simple'

17

| 'verbose'

18

| 'test'

19

| 'silent'

20

| ListrRendererFactory;

21

22

/**

23

* Renderer configuration in Listr options

24

*/

25

interface ListrBaseClassOptions<Ctx, Renderer, FallbackRenderer> {

26

/** Primary renderer to use */

27

renderer?: Renderer;

28

/** Fallback renderer when primary is unavailable */

29

fallbackRenderer?: FallbackRenderer;

30

/** Options for the primary renderer */

31

rendererOptions?: ListrGetRendererOptions<ListrGetRendererClassFromValue<Renderer>>;

32

/** Options for the fallback renderer */

33

fallbackRendererOptions?: ListrGetRendererOptions<ListrGetRendererClassFromValue<FallbackRenderer>>;

34

/** Condition to determine when to use fallback renderer */

35

fallbackRendererCondition?: boolean | (() => boolean);

36

/** Condition to determine when to use silent renderer */

37

silentRendererCondition?: boolean | (() => boolean);

38

}

39

```

40

41

### Default Renderer

42

43

Feature-rich renderer with spinners, colors, and interactive display elements. Requires TTY environment.

44

45

```typescript { .api }

46

/**

47

* Default renderer with rich interactive features

48

* Requires TTY environment for full functionality

49

*/

50

class DefaultRenderer extends ListrRenderer {

51

/** Indicates this renderer requires TTY */

52

static nonTTY: false;

53

54

/** Default renderer options */

55

static rendererOptions: {

56

/** Indentation settings */

57

indentation?: number;

58

/** Clear output on completion */

59

clearOutput?: boolean;

60

/** Show subtasks */

61

showSubtasks?: boolean;

62

/** Collapse finished tasks */

63

collapse?: boolean;

64

/** Collapse errors */

65

collapseErrors?: boolean;

66

/** Show error stack traces */

67

showErrorMessage?: boolean;

68

/** Suffix for task titles */

69

suffixSkips?: boolean;

70

/** Show skip messages */

71

suffixRetries?: boolean;

72

/** Show retry messages */

73

lazy?: boolean;

74

/** Lazy rendering mode */

75

removeEmptyLines?: boolean;

76

/** Format output lines */

77

formatOutput?: 'truncate' | 'wrap';

78

};

79

80

/** Task-specific options */

81

static rendererTaskOptions: {

82

/** Show output bar */

83

outputBar?: number;

84

/** Persistent output */

85

persistentOutput?: boolean;

86

/** Bottom bar for persistent output */

87

bottomBar?: boolean | number;

88

};

89

}

90

```

91

92

### Simple Renderer

93

94

Basic text-based renderer suitable for CI/CD environments and non-TTY outputs.

95

96

```typescript { .api }

97

/**

98

* Simple renderer for basic text output

99

* Works in both TTY and non-TTY environments

100

*/

101

class SimpleRenderer extends ListrRenderer {

102

/** Indicates this renderer works without TTY */

103

static nonTTY: true;

104

105

/** Simple renderer options */

106

static rendererOptions: {

107

/** Prefix character for tasks */

108

prefixWithTimestamp?: boolean;

109

/** Add timestamps to output */

110

logEmptyTitle?: boolean;

111

/** Log tasks with empty titles */

112

logTitleChange?: boolean;

113

};

114

}

115

```

116

117

### Verbose Renderer

118

119

Detailed logging renderer with timestamps and comprehensive output information.

120

121

```typescript { .api }

122

/**

123

* Verbose renderer with detailed logging and timestamps

124

* Works in both TTY and non-TTY environments

125

*/

126

class VerboseRenderer extends ListrRenderer {

127

/** Indicates this renderer works without TTY */

128

static nonTTY: true;

129

130

/** Verbose renderer options */

131

static rendererOptions: {

132

/** Show timestamps */

133

logEmptyTitle?: boolean;

134

/** Log tasks with empty titles */

135

logTitleChange?: boolean;

136

/** Log title changes */

137

useIcons?: boolean;

138

/** Use icons in output */

139

fields?: {

140

/** Configure timestamp field */

141

timestamp?: any;

142

/** Configure other logging fields */

143

[key: string]: any;

144

};

145

};

146

}

147

```

148

149

### Test Renderer

150

151

Specialized renderer for testing scenarios with serialized output and programmatic access.

152

153

```typescript { .api }

154

/**

155

* Test renderer for testing scenarios

156

* Provides serialized output for programmatic access

157

*/

158

class TestRenderer extends ListrRenderer {

159

/** Test renderer options */

160

static rendererOptions: {

161

/** Serialize test results */

162

serialize?: boolean;

163

/** Log level for test output */

164

logLevel?: 'silent' | 'error' | 'warn' | 'info' | 'verbose';

165

};

166

167

/** Get serialized test results */

168

getTestResults(): any[];

169

}

170

```

171

172

### Silent Renderer

173

174

Completely silent renderer that produces no output, useful for background operations.

175

176

```typescript { .api }

177

/**

178

* Silent renderer that produces no output

179

* Useful for background operations and scripting

180

*/

181

class SilentRenderer extends ListrRenderer {

182

/** Silent renderer has no configurable options */

183

static rendererOptions: {};

184

185

/** Silent renderer has no task options */

186

static rendererTaskOptions: {};

187

}

188

```

189

190

### Base Renderer Interface

191

192

Abstract base class that all renderers must implement.

193

194

```typescript { .api }

195

/**

196

* Abstract base class for all renderers

197

*/

198

abstract class ListrRenderer {

199

/** Default renderer-level options */

200

static rendererOptions: Record<PropertyKey, any>;

201

/** Default task-level options */

202

static rendererTaskOptions: Record<PropertyKey, any>;

203

/** Whether renderer works without TTY */

204

static nonTTY: boolean;

205

206

/**

207

* Create a new renderer instance

208

* @param tasks - Array of tasks to render

209

* @param options - Renderer options

210

* @param events - Event manager for listening to task events

211

*/

212

constructor(

213

tasks: Task[],

214

options: Record<PropertyKey, any>,

215

events?: ListrEventManager

216

);

217

218

/**

219

* Start rendering the task list

220

* @returns Promise that resolves when rendering starts

221

*/

222

abstract render(): void | Promise<void>;

223

224

/**

225

* End rendering and clean up

226

* @param err - Optional error that caused rendering to end

227

*/

228

abstract end(err?: Error): void;

229

}

230

231

/**

232

* Renderer factory function type

233

*/

234

type ListrRendererFactory = new (

235

tasks: Task[],

236

options: Record<PropertyKey, any>,

237

events?: ListrEventManager

238

) => ListrRenderer;

239

```

240

241

**Usage Examples:**

242

243

### Basic Renderer Configuration

244

245

```typescript

246

import { Listr, DefaultRenderer, SimpleRenderer } from "listr2";

247

248

// Use default renderer (automatic TTY detection)

249

const tasks1 = new Listr([

250

{ title: "Task 1", task: () => Promise.resolve() }

251

]);

252

253

// Explicitly specify renderer

254

const tasks2 = new Listr([

255

{ title: "Task 2", task: () => Promise.resolve() }

256

], {

257

renderer: 'default',

258

fallbackRenderer: 'simple'

259

});

260

261

// Force specific renderer

262

const tasks3 = new Listr([

263

{ title: "Task 3", task: () => Promise.resolve() }

264

], {

265

renderer: 'verbose'

266

});

267

```

268

269

### Renderer Options Configuration

270

271

```typescript

272

import { Listr } from "listr2";

273

274

// Default renderer with custom options

275

const tasks = new Listr([

276

{ title: "Task with custom rendering", task: () => Promise.resolve() }

277

], {

278

renderer: 'default',

279

rendererOptions: {

280

indentation: 4,

281

showSubtasks: true,

282

collapse: false,

283

collapseErrors: false,

284

showErrorMessage: true,

285

formatOutput: 'wrap'

286

}

287

});

288

289

// Simple renderer with timestamps

290

const simpleTasks = new Listr([

291

{ title: "Simple task", task: () => Promise.resolve() }

292

], {

293

renderer: 'simple',

294

rendererOptions: {

295

prefixWithTimestamp: true,

296

logEmptyTitle: false,

297

logTitleChange: true

298

}

299

});

300

```

301

302

### Conditional Renderer Selection

303

304

```typescript

305

import { Listr } from "listr2";

306

307

// Use different renderers based on environment

308

const tasks = new Listr([

309

{ title: "Environment-aware task", task: () => Promise.resolve() }

310

], {

311

renderer: 'default',

312

fallbackRenderer: 'simple',

313

// Use simple renderer in CI environments

314

fallbackRendererCondition: () => process.env.CI === 'true',

315

// Use silent renderer when QUIET flag is set

316

silentRendererCondition: () => process.env.QUIET === 'true'

317

});

318

```

319

320

### Task-Specific Renderer Options

321

322

```typescript

323

import { Listr } from "listr2";

324

325

const tasks = new Listr([

326

{

327

title: "Task with persistent output",

328

task: (ctx, task) => {

329

// This task will show persistent output at bottom

330

task.output = "Processing...";

331

return new Promise(resolve => {

332

setTimeout(() => {

333

task.output = "Completed!";

334

resolve(undefined);

335

}, 2000);

336

});

337

},

338

rendererOptions: {

339

persistentOutput: true,

340

bottomBar: true

341

}

342

},

343

{

344

title: "Task with output bar",

345

task: () => Promise.resolve(),

346

rendererOptions: {

347

outputBar: 10 // Show 10 lines of output

348

}

349

}

350

]);

351

```

352

353

### Testing with Test Renderer

354

355

```typescript

356

import { Listr } from "listr2";

357

358

// Create task list with test renderer

359

const tasks = new Listr([

360

{ title: "Test task 1", task: () => Promise.resolve() },

361

{ title: "Test task 2", task: () => Promise.reject(new Error("Test error")) }

362

], {

363

renderer: 'test',

364

rendererOptions: {

365

serialize: true,

366

logLevel: 'verbose'

367

}

368

});

369

370

try {

371

await tasks.run();

372

} catch (error) {

373

// Access serialized test results

374

const testResults = tasks.renderer.getTestResults();

375

console.log("Test results:", testResults);

376

}

377

```

378

379

### Custom Renderer Factory

380

381

```typescript

382

import { Listr, ListrRenderer } from "listr2";

383

384

// Create custom renderer class

385

class CustomRenderer extends ListrRenderer {

386

static nonTTY = true;

387

static rendererOptions = {

388

customOption: 'default-value'

389

};

390

391

render() {

392

console.log("Custom renderer started");

393

}

394

395

end(err?: Error) {

396

if (err) {

397

console.log("Custom renderer ended with error:", err.message);

398

} else {

399

console.log("Custom renderer completed successfully");

400

}

401

}

402

}

403

404

// Use custom renderer

405

const tasks = new Listr([

406

{ title: "Custom rendered task", task: () => Promise.resolve() }

407

], {

408

renderer: CustomRenderer,

409

rendererOptions: {

410

customOption: 'custom-value'

411

}

412

});

413

```

414

415

### Renderer Utility Functions

416

417

```typescript

418

import { getRenderer, getRendererClass } from "listr2";

419

420

// Get appropriate renderer based on conditions

421

const rendererInfo = getRenderer({

422

renderer: 'default',

423

fallbackRenderer: 'simple',

424

fallbackRendererCondition: () => !process.stdout.isTTY,

425

silentRendererCondition: () => process.env.SILENT === 'true'

426

});

427

428

console.log("Selected renderer:", rendererInfo.selection);

429

console.log("Renderer class:", rendererInfo.renderer);

430

console.log("Renderer options:", rendererInfo.options);

431

432

// Get renderer class from string value

433

const RendererClass = getRendererClass('verbose');

434

```

435

436

## Types

437

438

```typescript { .api }

439

/**

440

* Renderer selection state

441

*/

442

enum ListrRendererSelection {

443

PRIMARY = 'PRIMARY',

444

SECONDARY = 'SECONDARY',

445

SILENT = 'SILENT'

446

}

447

448

/**

449

* Supported renderer information

450

*/

451

interface SupportedRenderer {

452

renderer: ListrRendererFactory;

453

options: Record<PropertyKey, any>;

454

selection: ListrRendererSelection;

455

}

456

457

/**

458

* Generic renderer options type helpers

459

*/

460

type ListrGetRendererClassFromValue<T extends ListrRendererValue> =

461

T extends ListrRendererFactory ? T :

462

T extends 'default' ? typeof DefaultRenderer :

463

T extends 'simple' ? typeof SimpleRenderer :

464

T extends 'verbose' ? typeof VerboseRenderer :

465

T extends 'test' ? typeof TestRenderer :

466

T extends 'silent' ? typeof SilentRenderer :

467

never;

468

469

type ListrGetRendererOptions<T extends ListrRendererFactory> =

470

T extends { rendererOptions: infer R } ? R : Record<PropertyKey, any>;

471

472

type ListrGetRendererTaskOptions<T extends ListrRendererFactory> =

473

T extends { rendererTaskOptions: infer R } ? R : Record<PropertyKey, any>;

474

475

/**

476

* Environment detection utilities

477

*/

478

interface RendererEnvironment {

479

/** Whether current environment supports TTY */

480

isTTY: boolean;

481

/** Whether current environment supports Unicode */

482

isUnicode: boolean;

483

/** Whether colors are supported */

484

supportsColor: boolean;

485

}

486

```