@promptctl/rich-js 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -15
- package/dist/core/console.d.ts +29 -11
- package/dist/core/console.d.ts.map +1 -1
- package/dist/core/console.js +86 -30
- package/dist/core/console.js.map +1 -1
- package/dist/core/render.d.ts.map +1 -1
- package/dist/core/render.js +8 -1
- package/dist/core/render.js.map +1 -1
- package/dist/core/sanitize.d.ts +16 -0
- package/dist/core/sanitize.d.ts.map +1 -0
- package/dist/core/sanitize.js +19 -0
- package/dist/core/sanitize.js.map +1 -0
- package/dist/core/strip.d.ts +16 -74
- package/dist/core/strip.d.ts.map +1 -1
- package/dist/core/strip.js +37 -82
- package/dist/core/strip.js.map +1 -1
- package/dist/core/style.d.ts +1 -0
- package/dist/core/style.d.ts.map +1 -1
- package/dist/core/style.js +38 -5
- package/dist/core/style.js.map +1 -1
- package/dist/core/text.d.ts +54 -1
- package/dist/core/text.d.ts.map +1 -1
- package/dist/core/text.js +194 -12
- package/dist/core/text.js.map +1 -1
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/node/prompt.d.ts +22 -0
- package/dist/node/prompt.d.ts.map +1 -0
- package/dist/node/prompt.js +31 -0
- package/dist/node/prompt.js.map +1 -0
- package/dist/node/save.d.ts +22 -0
- package/dist/node/save.d.ts.map +1 -0
- package/dist/node/save.js +22 -0
- package/dist/node/save.js.map +1 -0
- package/dist/renderables/prompt.d.ts +31 -6
- package/dist/renderables/prompt.d.ts.map +1 -1
- package/dist/renderables/prompt.js +39 -22
- package/dist/renderables/prompt.js.map +1 -1
- package/dist/widgets/event-router.d.ts +16 -14
- package/dist/widgets/event-router.d.ts.map +1 -1
- package/dist/widgets/event-router.js +71 -38
- package/dist/widgets/event-router.js.map +1 -1
- package/dist/widgets/host-stream.d.ts +31 -0
- package/dist/widgets/host-stream.d.ts.map +1 -0
- package/dist/widgets/host-stream.js +36 -0
- package/dist/widgets/host-stream.js.map +1 -0
- package/dist/widgets/index.d.ts +3 -0
- package/dist/widgets/index.d.ts.map +1 -1
- package/dist/widgets/index.js +2 -0
- package/dist/widgets/index.js.map +1 -1
- package/dist/widgets/screen.d.ts +12 -5
- package/dist/widgets/screen.d.ts.map +1 -1
- package/dist/widgets/screen.js +9 -11
- package/dist/widgets/screen.js.map +1 -1
- package/dist/widgets/terminal-host.d.ts +188 -0
- package/dist/widgets/terminal-host.d.ts.map +1 -0
- package/dist/widgets/terminal-host.js +258 -0
- package/dist/widgets/terminal-host.js.map +1 -0
- package/package.json +20 -6
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TerminalHost — the capability seam between the interactive runtime and its
|
|
3
|
+
* I/O environment.
|
|
4
|
+
*
|
|
5
|
+
* [LAW:locality-or-seam] The missing seam *was* the missing type. Before this
|
|
6
|
+
* type existed, Screen and EventRouter reached for ambient `process.stdin`/
|
|
7
|
+
* `process.stdout`, which crystallised them to node. With a `TerminalHost`
|
|
8
|
+
* value flowing across one boundary, the same runtime code runs against any
|
|
9
|
+
* implementation — node's TTY (`NodeTerminalHost`, this file) or a browser
|
|
10
|
+
* xterm.js terminal (a downstream ticket's adapter).
|
|
11
|
+
*
|
|
12
|
+
* [LAW:dataflow-not-control-flow] The runtime never branches on "am I in
|
|
13
|
+
* node or browser." The host is the value that differs; the code path is
|
|
14
|
+
* the same. Variability lives in which host is constructed at the program
|
|
15
|
+
* entry, not in any `if` inside the runtime.
|
|
16
|
+
*
|
|
17
|
+
* [LAW:no-shared-mutable-globals] This file is the *single owner* of node
|
|
18
|
+
* TTY access in the codebase. Every other module receives a `TerminalHost`
|
|
19
|
+
* from outside. If you find yourself reaching for `process.stdin`,
|
|
20
|
+
* `process.stdout`, or `setRawMode` anywhere else in the runtime or in a
|
|
21
|
+
* demo, fix the call site to take a `TerminalHost` parameter instead —
|
|
22
|
+
* the seam is already here; use it.
|
|
23
|
+
*
|
|
24
|
+
* [boundaries: capabilities over context] A `TerminalHost` grants exactly
|
|
25
|
+
* the I/O capabilities the runtime needs: write bytes, read input, query
|
|
26
|
+
* size, observe resize, switch raw mode, lifecycle. It is not an
|
|
27
|
+
* omniscient handle to "the process."
|
|
28
|
+
*/
|
|
29
|
+
const DEFAULT_COLS = 80;
|
|
30
|
+
const DEFAULT_ROWS = 24;
|
|
31
|
+
export class NodeTerminalHost {
|
|
32
|
+
stdin;
|
|
33
|
+
stdout;
|
|
34
|
+
dataHandlers = new Set();
|
|
35
|
+
resizeHandlers = new Set();
|
|
36
|
+
dataListener;
|
|
37
|
+
resizeListener;
|
|
38
|
+
rawModeRequested = false;
|
|
39
|
+
constructor(options = {}) {
|
|
40
|
+
// [LAW:no-shared-mutable-globals] The ONLY place in the codebase that
|
|
41
|
+
// reaches for `process.stdin`/`process.stdout` directly. All other
|
|
42
|
+
// callers receive a `TerminalHost` and stay environment-agnostic.
|
|
43
|
+
this.stdin = options.stdin ?? process.stdin;
|
|
44
|
+
this.stdout = options.stdout ?? process.stdout;
|
|
45
|
+
}
|
|
46
|
+
get isTTY() {
|
|
47
|
+
return !!this.stdin.isTTY && !!this.stdout.isTTY;
|
|
48
|
+
}
|
|
49
|
+
write(data) {
|
|
50
|
+
this.stdout.write(data);
|
|
51
|
+
}
|
|
52
|
+
size() {
|
|
53
|
+
return {
|
|
54
|
+
cols: this.stdout.columns ?? DEFAULT_COLS,
|
|
55
|
+
rows: this.stdout.rows ?? DEFAULT_ROWS,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
setRawMode(raw) {
|
|
59
|
+
this.rawModeRequested = raw;
|
|
60
|
+
this.applyRawMode(raw);
|
|
61
|
+
}
|
|
62
|
+
// [LAW:single-enforcer] One site decides what to do when toggling raw
|
|
63
|
+
// mode on the underlying transport fails. Both `setRawMode` (call from
|
|
64
|
+
// outside) and `stop` (cleanup) go through this helper so neither
|
|
65
|
+
// caller has to branch on capability or exception-handling.
|
|
66
|
+
//
|
|
67
|
+
// [LAW:dataflow-not-control-flow] Two shapes of "the transport can't do
|
|
68
|
+
// this" are absorbed identically: the optional chain handles "method
|
|
69
|
+
// missing" (non-TTY streams, PassThrough in tests); the try/catch
|
|
70
|
+
// handles "method exists but threw" (node's `setRawMode` throws on
|
|
71
|
+
// closed or non-TTY streams). Callers see neither shape — they always
|
|
72
|
+
// call `setRawMode(bool)`, and the host decides what's possible.
|
|
73
|
+
//
|
|
74
|
+
// The catch is silent because the only call sites are lifecycle
|
|
75
|
+
// transitions: if the stream is already gone, there is nothing
|
|
76
|
+
// semantically meaningful for the host to do, and surfacing the
|
|
77
|
+
// exception would only make teardown brittle without giving the caller
|
|
78
|
+
// a recovery path. The demos this replaces did `try { ... } catch {}`
|
|
79
|
+
// at every call site for exactly this reason — absorbing it once here
|
|
80
|
+
// means the pattern stops spreading.
|
|
81
|
+
applyRawMode(raw) {
|
|
82
|
+
try {
|
|
83
|
+
this.stdin.setRawMode?.(raw);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Underlying stream couldn't honor the request (closed, no longer
|
|
87
|
+
// a TTY, etc.). Lifecycle continues.
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
onData(handler) {
|
|
91
|
+
this.dataHandlers.add(handler);
|
|
92
|
+
// [LAW:single-enforcer] One underlying `data` listener fans out to all
|
|
93
|
+
// subscribers — keeps stdin's flowing/paused state derivable from
|
|
94
|
+
// "any subscribers?" instead of from per-call ref-counts scattered
|
|
95
|
+
// through the runtime.
|
|
96
|
+
if (!this.dataListener) {
|
|
97
|
+
this.dataListener = (chunk) => {
|
|
98
|
+
for (const h of this.dataHandlers)
|
|
99
|
+
h(chunk);
|
|
100
|
+
};
|
|
101
|
+
this.stdin.on("data", this.dataListener);
|
|
102
|
+
this.stdin.resume?.();
|
|
103
|
+
}
|
|
104
|
+
return () => {
|
|
105
|
+
this.dataHandlers.delete(handler);
|
|
106
|
+
if (this.dataHandlers.size === 0 && this.dataListener) {
|
|
107
|
+
this.stdin.off("data", this.dataListener);
|
|
108
|
+
this.dataListener = undefined;
|
|
109
|
+
// Returning stdin to paused state mirrors the symmetric "no
|
|
110
|
+
// subscribers → no flow" invariant. Without this, removing the
|
|
111
|
+
// last subscriber leaves stdin in flowing mode and the process
|
|
112
|
+
// hangs forever waiting for an event nobody is listening for.
|
|
113
|
+
this.stdin.pause?.();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
onResize(handler) {
|
|
118
|
+
this.resizeHandlers.add(handler);
|
|
119
|
+
if (!this.resizeListener) {
|
|
120
|
+
this.resizeListener = () => {
|
|
121
|
+
const size = this.size();
|
|
122
|
+
for (const h of this.resizeHandlers)
|
|
123
|
+
h(size);
|
|
124
|
+
};
|
|
125
|
+
this.stdout.on("resize", this.resizeListener);
|
|
126
|
+
}
|
|
127
|
+
return () => {
|
|
128
|
+
this.resizeHandlers.delete(handler);
|
|
129
|
+
if (this.resizeHandlers.size === 0 && this.resizeListener) {
|
|
130
|
+
this.stdout.off("resize", this.resizeListener);
|
|
131
|
+
this.resizeListener = undefined;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
start() {
|
|
136
|
+
// No-op on node: stdin/stdout are always available. Lifecycle exists
|
|
137
|
+
// so the browser host (downstream ticket) can attach to the DOM here
|
|
138
|
+
// without the runtime branching on "do I need to start?"
|
|
139
|
+
}
|
|
140
|
+
stop() {
|
|
141
|
+
// [LAW:one-source-of-truth] Symmetric teardown: drop every subscriber
|
|
142
|
+
// and detach the underlying stream listeners. After stop(), the host
|
|
143
|
+
// is in the same shape a freshly-constructed one would be in. Calling
|
|
144
|
+
// stop() repeatedly is safe — the dataListener/resizeListener guards
|
|
145
|
+
// make later calls no-ops.
|
|
146
|
+
if (this.dataListener) {
|
|
147
|
+
this.stdin.off("data", this.dataListener);
|
|
148
|
+
this.dataListener = undefined;
|
|
149
|
+
this.stdin.pause?.();
|
|
150
|
+
}
|
|
151
|
+
if (this.resizeListener) {
|
|
152
|
+
this.stdout.off("resize", this.resizeListener);
|
|
153
|
+
this.resizeListener = undefined;
|
|
154
|
+
}
|
|
155
|
+
this.dataHandlers.clear();
|
|
156
|
+
this.resizeHandlers.clear();
|
|
157
|
+
if (this.rawModeRequested) {
|
|
158
|
+
this.applyRawMode(false);
|
|
159
|
+
this.rawModeRequested = false;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export class BrowserTerminalHost {
|
|
164
|
+
terminal;
|
|
165
|
+
dataHandlers = new Set();
|
|
166
|
+
resizeHandlers = new Set();
|
|
167
|
+
dataSubscription;
|
|
168
|
+
resizeSubscription;
|
|
169
|
+
constructor(options) {
|
|
170
|
+
this.terminal = options.terminal;
|
|
171
|
+
}
|
|
172
|
+
// [LAW:dataflow-not-control-flow] xterm.js is always an interactive
|
|
173
|
+
// terminal — there is no "non-TTY" code path in the browser. The
|
|
174
|
+
// runtime never branches on the value; this is the only sensible
|
|
175
|
+
// constant for this host.
|
|
176
|
+
get isTTY() {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
write(data) {
|
|
180
|
+
this.terminal.write(data);
|
|
181
|
+
}
|
|
182
|
+
size() {
|
|
183
|
+
return { cols: this.terminal.cols, rows: this.terminal.rows };
|
|
184
|
+
}
|
|
185
|
+
// [LAW:dataflow-not-control-flow] xterm.js delivers keystrokes raw
|
|
186
|
+
// unconditionally — there is no cooked mode to toggle. The no-op
|
|
187
|
+
// matches the TerminalHost contract's documented "silently no-op when
|
|
188
|
+
// the transport has no cooked mode," so callers stay uniform across
|
|
189
|
+
// hosts. (Mirror: NodeTerminalHost on a non-TTY stream takes the same
|
|
190
|
+
// no-op path via the optional-chain in `applyRawMode`.)
|
|
191
|
+
setRawMode(_raw) { }
|
|
192
|
+
// [LAW:single-enforcer] One underlying `terminal.onData` subscription
|
|
193
|
+
// fans out to every host-level handler — the same lazy-attach,
|
|
194
|
+
// last-unsubscribe-detaches shape as NodeTerminalHost.onData. The
|
|
195
|
+
// runtime never sees the underlying subscription; it sees a single
|
|
196
|
+
// uniform `(handler) => Unsubscribe` API across hosts.
|
|
197
|
+
onData(handler) {
|
|
198
|
+
this.dataHandlers.add(handler);
|
|
199
|
+
if (!this.dataSubscription) {
|
|
200
|
+
this.dataSubscription = this.terminal.onData((chunk) => {
|
|
201
|
+
for (const h of this.dataHandlers)
|
|
202
|
+
h(chunk);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
return () => {
|
|
206
|
+
this.dataHandlers.delete(handler);
|
|
207
|
+
if (this.dataHandlers.size === 0 && this.dataSubscription) {
|
|
208
|
+
this.dataSubscription.dispose();
|
|
209
|
+
this.dataSubscription = undefined;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
onResize(handler) {
|
|
214
|
+
this.resizeHandlers.add(handler);
|
|
215
|
+
if (!this.resizeSubscription) {
|
|
216
|
+
this.resizeSubscription = this.terminal.onResize((size) => {
|
|
217
|
+
const snapshot = { cols: size.cols, rows: size.rows };
|
|
218
|
+
for (const h of this.resizeHandlers)
|
|
219
|
+
h(snapshot);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
return () => {
|
|
223
|
+
this.resizeHandlers.delete(handler);
|
|
224
|
+
if (this.resizeHandlers.size === 0 && this.resizeSubscription) {
|
|
225
|
+
this.resizeSubscription.dispose();
|
|
226
|
+
this.resizeSubscription = undefined;
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
start() {
|
|
231
|
+
// [LAW:one-source-of-truth] The host does NOT own the terminal's DOM
|
|
232
|
+
// lifecycle (`terminal.open` / `terminal.dispose`). That is the
|
|
233
|
+
// caller's responsibility, exactly as NodeTerminalHost does not own
|
|
234
|
+
// `process.stdin`/`process.stdout`. start() is here so the runtime
|
|
235
|
+
// can call it uniformly across hosts; for this host there is
|
|
236
|
+
// nothing to do at this seam.
|
|
237
|
+
}
|
|
238
|
+
stop() {
|
|
239
|
+
// [LAW:one-source-of-truth] Symmetric teardown mirroring
|
|
240
|
+
// NodeTerminalHost.stop: drop every host-level subscriber and
|
|
241
|
+
// dispose the underlying terminal subscriptions. The terminal
|
|
242
|
+
// itself stays alive — re-subscribing via onData/onResize after
|
|
243
|
+
// stop() works, since the lazy-attach path re-creates the
|
|
244
|
+
// subscription on next subscribe. Calling stop() repeatedly is
|
|
245
|
+
// safe — the subscription guards make later calls no-ops.
|
|
246
|
+
if (this.dataSubscription) {
|
|
247
|
+
this.dataSubscription.dispose();
|
|
248
|
+
this.dataSubscription = undefined;
|
|
249
|
+
}
|
|
250
|
+
if (this.resizeSubscription) {
|
|
251
|
+
this.resizeSubscription.dispose();
|
|
252
|
+
this.resizeSubscription = undefined;
|
|
253
|
+
}
|
|
254
|
+
this.dataHandlers.clear();
|
|
255
|
+
this.resizeHandlers.clear();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
//# sourceMappingURL=terminal-host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-host.js","sourceRoot":"","sources":["../../src/widgets/terminal-host.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptctl/rich-js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Rich text and beautiful formatting in the terminal — a TypeScript port of Python's Rich",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -21,6 +21,14 @@
|
|
|
21
21
|
"./template-bindings": {
|
|
22
22
|
"types": "./dist/template-bindings/index.d.ts",
|
|
23
23
|
"import": "./dist/template-bindings/index.js"
|
|
24
|
+
},
|
|
25
|
+
"./node/save": {
|
|
26
|
+
"types": "./dist/node/save.d.ts",
|
|
27
|
+
"import": "./dist/node/save.js"
|
|
28
|
+
},
|
|
29
|
+
"./node/prompt": {
|
|
30
|
+
"types": "./dist/node/prompt.d.ts",
|
|
31
|
+
"import": "./dist/node/prompt.js"
|
|
24
32
|
}
|
|
25
33
|
},
|
|
26
34
|
"files": [
|
|
@@ -30,10 +38,10 @@
|
|
|
30
38
|
"build": "tsc",
|
|
31
39
|
"test": "vitest run",
|
|
32
40
|
"test:watch": "vitest",
|
|
33
|
-
"lint": "tsc --noEmit",
|
|
41
|
+
"lint": "tsc --noEmit && tsc -p tsconfig.scripts.json",
|
|
34
42
|
"clean": "rm -rf dist",
|
|
35
|
-
"docs:dev": "vitepress dev docs",
|
|
36
|
-
"docs:build": "vitepress build docs",
|
|
43
|
+
"docs:dev": "npm run demos:build && vitepress dev docs",
|
|
44
|
+
"docs:build": "npm run demos:build && vitepress build docs",
|
|
37
45
|
"docs:preview": "vitepress preview docs",
|
|
38
46
|
"demo": "tsc -p tsconfig.demo.json && node dist-demo/examples/rich-explore/index.js",
|
|
39
47
|
"demo:build": "tsc -p tsconfig.demo.json",
|
|
@@ -44,7 +52,11 @@
|
|
|
44
52
|
"demo:dropdown": "tsc -p tsconfig.demo.json && node dist-demo/examples/dropdown-demo/index.js",
|
|
45
53
|
"dash": "tsc -p tsconfig.demo.json && node dist-demo/examples/rich-dash/index.js",
|
|
46
54
|
"template-bindings": "tsc -p tsconfig.demo.json && node dist-demo/examples/rich-template-bindings/index.js",
|
|
47
|
-
"themes-and-color-studio": "tsc -p tsconfig.demo.json && node dist-demo/examples/themes-and-color-studio/index.js"
|
|
55
|
+
"themes-and-color-studio": "tsc -p tsconfig.demo.json && node dist-demo/examples/themes-and-color-studio/index.js",
|
|
56
|
+
"harness:browser-host": "tsc -p tsconfig.demo.json && echo 'Serving harness at http://localhost:8080/examples/browser-terminal-host-harness/' && npx --yes http-server@14.1.1 -p 8080 -c-1 -s .",
|
|
57
|
+
"demos:build": "tsc -p tsconfig.demo.json && vite build --config vite.config.demos.ts",
|
|
58
|
+
"demos:preview": "vite preview --config vite.config.demos.ts",
|
|
59
|
+
"test:demos": "playwright test"
|
|
48
60
|
},
|
|
49
61
|
"keywords": [
|
|
50
62
|
"terminal",
|
|
@@ -61,11 +73,13 @@
|
|
|
61
73
|
],
|
|
62
74
|
"license": "MIT",
|
|
63
75
|
"engines": {
|
|
64
|
-
"node": ">=
|
|
76
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
65
77
|
},
|
|
66
78
|
"devDependencies": {
|
|
79
|
+
"@playwright/test": "^1.60.0",
|
|
67
80
|
"@types/node": "^25.5.0",
|
|
68
81
|
"typescript": "^5.7.0",
|
|
82
|
+
"vite": "^7.3.3",
|
|
69
83
|
"vitepress": "^1.6.4",
|
|
70
84
|
"vitest": "^3.0.0"
|
|
71
85
|
},
|