-
-
Notifications
You must be signed in to change notification settings - Fork 972
Expand file tree
/
Copy pathrender.ts
More file actions
129 lines (115 loc) · 2.63 KB
/
render.ts
File metadata and controls
129 lines (115 loc) · 2.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import {Stream} from 'node:stream';
import process from 'node:process';
import type {ReactNode} from 'react';
import Ink, {type Options as InkOptions} from './ink.js';
import instances from './instances.js';
export type RenderOptions = {
/**
* Output stream where app will be rendered.
*
* @default process.stdout
*/
stdout?: NodeJS.WriteStream;
/**
* Input stream where app will listen for input.
*
* @default process.stdin
*/
stdin?: NodeJS.ReadStream;
/**
* Error stream.
* @default process.stderr
*/
stderr?: NodeJS.WriteStream;
/**
* If true, each update will be rendered as a separate output, without replacing the previous one.
*
* @default false
*/
debug?: boolean;
/**
* Configure whether Ink should listen to Ctrl+C keyboard input and exit the app. This is needed in case `process.stdin` is in raw mode, because then Ctrl+C is ignored by default and process is expected to handle it manually.
*
* @default true
*/
exitOnCtrlC?: boolean;
/**
* Patch console methods to ensure console output doesn't mix with Ink output.
*
* @default true
*/
patchConsole?: boolean;
};
export type Instance = {
/**
* Replace previous root node with a new one or update props of the current root node.
*/
rerender: Ink['render'];
/**
* Manually unmount the whole Ink app.
*/
unmount: Ink['unmount'];
/**
* Returns a promise, which resolves when app is unmounted.
*/
waitUntilExit: Ink['waitUntilExit'];
cleanup: () => void;
/**
* Clear output.
*/
clear: () => void;
};
/**
* Mount a component and render the output.
*/
const render = (
node: ReactNode,
options?: NodeJS.WriteStream | RenderOptions
): Instance => {
const inkOptions: InkOptions = {
stdout: process.stdout,
stdin: process.stdin,
stderr: process.stderr,
debug: false,
exitOnCtrlC: true,
patchConsole: true,
...getOptions(options)
};
const instance: Ink = getInstance(
inkOptions.stdout,
() => new Ink(inkOptions)
);
instance.render(node);
return {
rerender: instance.render,
unmount() {
instance.unmount();
},
waitUntilExit: instance.waitUntilExit,
cleanup: () => instances.delete(inkOptions.stdout),
clear: instance.clear
};
};
export default render;
const getOptions = (
stdout: NodeJS.WriteStream | RenderOptions | undefined = {}
): RenderOptions => {
if (stdout instanceof Stream) {
return {
stdout,
stdin: process.stdin
};
}
return stdout;
};
const getInstance = (
stdout: NodeJS.WriteStream,
createInstance: () => Ink
): Ink => {
let instance = instances.get(stdout);
if (!instance) {
instance = createInstance();
instances.set(stdout, instance);
}
return instance;
};