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
```