@promptctl/rich-js 0.8.0 → 0.9.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 +68 -1
- package/dist/core/box.d.ts +93 -39
- package/dist/core/box.d.ts.map +1 -1
- package/dist/core/box.js +348 -490
- package/dist/core/box.js.map +1 -1
- package/dist/core/color.d.ts.map +1 -1
- package/dist/core/color.js +22 -8
- package/dist/core/color.js.map +1 -1
- package/dist/core/console.d.ts +2 -4
- package/dist/core/console.d.ts.map +1 -1
- package/dist/core/console.js +35 -24
- package/dist/core/console.js.map +1 -1
- package/dist/core/highlighter.d.ts +2 -1
- package/dist/core/highlighter.d.ts.map +1 -1
- package/dist/core/highlighter.js +28 -6
- package/dist/core/highlighter.js.map +1 -1
- package/dist/{renderables → core}/json.d.ts +8 -3
- package/dist/core/json.d.ts.map +1 -0
- package/dist/{renderables → core}/json.js +7 -2
- package/dist/core/json.js.map +1 -0
- package/dist/core/markup.d.ts +6 -7
- package/dist/core/markup.d.ts.map +1 -1
- package/dist/core/markup.js +124 -32
- package/dist/core/markup.js.map +1 -1
- package/dist/core/pretty.d.ts +56 -21
- package/dist/core/pretty.d.ts.map +1 -1
- package/dist/core/pretty.js +210 -116
- package/dist/core/pretty.js.map +1 -1
- package/dist/core/protocol.d.ts +16 -0
- package/dist/core/protocol.d.ts.map +1 -1
- package/dist/core/protocol.js +13 -0
- package/dist/core/protocol.js.map +1 -1
- package/dist/core/segment.d.ts +5 -0
- package/dist/core/segment.d.ts.map +1 -1
- package/dist/core/segment.js +9 -3
- package/dist/core/segment.js.map +1 -1
- package/dist/core/strip.d.ts +9 -5
- package/dist/core/strip.d.ts.map +1 -1
- package/dist/core/strip.js +39 -41
- package/dist/core/strip.js.map +1 -1
- package/dist/core/style.d.ts +19 -0
- package/dist/core/style.d.ts.map +1 -1
- package/dist/core/style.js +46 -38
- package/dist/core/style.js.map +1 -1
- package/dist/core/text.d.ts +102 -4
- package/dist/core/text.d.ts.map +1 -1
- package/dist/core/text.js +322 -184
- package/dist/core/text.js.map +1 -1
- package/dist/core/wrap.d.ts +42 -0
- package/dist/core/wrap.d.ts.map +1 -0
- package/dist/core/wrap.js +128 -0
- package/dist/core/wrap.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/renderables/markdown.d.ts +1 -1
- package/dist/renderables/markdown.d.ts.map +1 -1
- package/dist/renderables/markdown.js +7 -14
- package/dist/renderables/markdown.js.map +1 -1
- package/dist/renderables/padding.d.ts +1 -1
- package/dist/renderables/padding.d.ts.map +1 -1
- package/dist/renderables/padding.js +5 -11
- package/dist/renderables/padding.js.map +1 -1
- package/dist/renderables/panel.d.ts +4 -4
- package/dist/renderables/panel.d.ts.map +1 -1
- package/dist/renderables/panel.js +39 -39
- package/dist/renderables/panel.js.map +1 -1
- package/dist/renderables/progress.d.ts +3 -3
- package/dist/renderables/progress.d.ts.map +1 -1
- package/dist/renderables/progress.js +11 -9
- package/dist/renderables/progress.js.map +1 -1
- package/dist/renderables/progressBar.d.ts +3 -3
- package/dist/renderables/progressBar.d.ts.map +1 -1
- package/dist/renderables/progressBar.js +9 -15
- package/dist/renderables/progressBar.js.map +1 -1
- package/dist/renderables/prompt.js +1 -1
- package/dist/renderables/prompt.js.map +1 -1
- package/dist/renderables/rule.d.ts +1 -1
- package/dist/renderables/rule.d.ts.map +1 -1
- package/dist/renderables/rule.js +5 -10
- package/dist/renderables/rule.js.map +1 -1
- package/dist/renderables/spinner.d.ts +2 -2
- package/dist/renderables/spinner.d.ts.map +1 -1
- package/dist/renderables/spinner.js +6 -11
- package/dist/renderables/spinner.js.map +1 -1
- package/dist/renderables/status.d.ts.map +1 -1
- package/dist/renderables/status.js +5 -11
- package/dist/renderables/status.js.map +1 -1
- package/dist/renderables/table.d.ts +54 -16
- package/dist/renderables/table.d.ts.map +1 -1
- package/dist/renderables/table.js +239 -99
- package/dist/renderables/table.js.map +1 -1
- package/dist/renderables/traceback.d.ts +1 -1
- package/dist/renderables/traceback.d.ts.map +1 -1
- package/dist/renderables/traceback.js +9 -8
- package/dist/renderables/traceback.js.map +1 -1
- package/dist/renderables/tree.d.ts +2 -2
- package/dist/renderables/tree.d.ts.map +1 -1
- package/dist/renderables/tree.js +16 -22
- package/dist/renderables/tree.js.map +1 -1
- package/dist/template-bindings/helpers.d.ts.map +1 -1
- package/dist/template-bindings/helpers.js +19 -1
- package/dist/template-bindings/helpers.js.map +1 -1
- package/package.json +20 -4
- package/dist/renderables/json.d.ts.map +0 -1
- package/dist/renderables/json.js.map +0 -1
- package/dist/renderables/pretty.d.ts +0 -29
- package/dist/renderables/pretty.d.ts.map +0 -1
- package/dist/renderables/pretty.js +0 -141
- package/dist/renderables/pretty.js.map +0 -1
- package/dist/themes/paletteResolver.d.ts +0 -35
- package/dist/themes/paletteResolver.d.ts.map +0 -1
- package/dist/themes/paletteResolver.js +0 -88
- package/dist/themes/paletteResolver.js.map +0 -1
- package/dist/widgets/host-stream.d.ts +0 -31
- package/dist/widgets/host-stream.d.ts.map +0 -1
- package/dist/widgets/host-stream.js +0 -36
- package/dist/widgets/host-stream.js.map +0 -1
- package/dist/widgets/terminal-host.d.ts +0 -138
- package/dist/widgets/terminal-host.d.ts.map +0 -1
- package/dist/widgets/terminal-host.js +0 -127
- package/dist/widgets/terminal-host.js.map +0 -1
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { darken, alphaBlend, contrastFor } from "./colorMath.js";
|
|
2
|
-
const AUTO_NAME = "auto";
|
|
3
|
-
// Modifier matches the trailing "-darken-N" or "-lighten-N" of a name part.
|
|
4
|
-
// Anchored right (`.+` is greedy) because var names themselves contain
|
|
5
|
-
// hyphens — `"primary-background-darken-3"` must split into the var
|
|
6
|
-
// `primary-background` and the modifier `darken-3`, not `primary` /
|
|
7
|
-
// `background-darken-3`.
|
|
8
|
-
const MODIFIER_RE = /^(.+)-(darken|lighten)-(\d+)$/;
|
|
9
|
-
const ALPHA_RE = /^(\d+(?:\.\d+)?)%$/;
|
|
10
|
-
function parse(spec) {
|
|
11
|
-
const trimmed = spec.trim();
|
|
12
|
-
if (trimmed === "")
|
|
13
|
-
return null;
|
|
14
|
-
const [namePart, alphaPart, ...rest] = trimmed.split(/\s+/);
|
|
15
|
-
if (namePart === undefined || rest.length > 0)
|
|
16
|
-
return null;
|
|
17
|
-
let alpha = null;
|
|
18
|
-
if (alphaPart !== undefined) {
|
|
19
|
-
const m = ALPHA_RE.exec(alphaPart);
|
|
20
|
-
if (m === null)
|
|
21
|
-
return null;
|
|
22
|
-
const pct = parseFloat(m[1]);
|
|
23
|
-
if (pct < 0 || pct > 100)
|
|
24
|
-
return null;
|
|
25
|
-
alpha = pct / 100;
|
|
26
|
-
}
|
|
27
|
-
const mod = MODIFIER_RE.exec(namePart);
|
|
28
|
-
if (mod !== null) {
|
|
29
|
-
const levels = parseInt(mod[3], 10);
|
|
30
|
-
return {
|
|
31
|
-
name: mod[1],
|
|
32
|
-
darkenLevels: mod[2] === "darken" ? levels : -levels,
|
|
33
|
-
alpha,
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
return { name: namePart, darkenLevels: 0, alpha };
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Resolves Textual-style spec strings against a Palette into ColorRgba values.
|
|
40
|
-
*
|
|
41
|
-
* Spec grammar:
|
|
42
|
-
* spec = name ("-darken-" N | "-lighten-" N)? (" " NN "%")?
|
|
43
|
-
* name = "auto" | <palette var name>
|
|
44
|
-
*
|
|
45
|
-
* Examples (against gruvbox):
|
|
46
|
-
* "primary" → palette["primary"]
|
|
47
|
-
* "primary-background" → palette["primary-background"] (name has hyphens)
|
|
48
|
-
* "primary-darken-3" → darken(palette["primary"], 3)
|
|
49
|
-
* "primary 50%" → alphaBlend(palette["primary"], against, 0.5)
|
|
50
|
-
* "auto 33%" → alphaBlend(contrastFor(against), against, 0.33)
|
|
51
|
-
* "primary-darken-3 50%" → alphaBlend(darken(palette["primary"], 3), against, 0.5)
|
|
52
|
-
*
|
|
53
|
-
* Returns null on: invalid syntax, missing var, or missing required `against`.
|
|
54
|
-
* Pure: same inputs always yield the same output, no internal state.
|
|
55
|
-
*/
|
|
56
|
-
export class PaletteResolver {
|
|
57
|
-
palette;
|
|
58
|
-
constructor(palette) {
|
|
59
|
-
this.palette = palette;
|
|
60
|
-
}
|
|
61
|
-
resolve(spec, ctx) {
|
|
62
|
-
const parsed = parse(spec);
|
|
63
|
-
if (parsed === null)
|
|
64
|
-
return null;
|
|
65
|
-
// [LAW:one-type-per-behavior] `auto` is a synthetic var whose "lookup"
|
|
66
|
-
// depends on ctx; named vars look up in the palette. Both produce a
|
|
67
|
-
// ColorRgba | null, so the pipeline downstream is identical.
|
|
68
|
-
const base = this.lookupBase(parsed.name, ctx);
|
|
69
|
-
if (base === null)
|
|
70
|
-
return null;
|
|
71
|
-
// [LAW:dataflow-not-control-flow] darken at level 0 is a no-op (modulo
|
|
72
|
-
// ±1 RGB roundtrip); we always run it and let the data (levels) decide
|
|
73
|
-
// the magnitude. Negative levels lighten — same op, different value.
|
|
74
|
-
const modified = darken(base, parsed.darkenLevels);
|
|
75
|
-
if (parsed.alpha === null)
|
|
76
|
-
return modified;
|
|
77
|
-
if (!ctx?.against)
|
|
78
|
-
return null;
|
|
79
|
-
return alphaBlend(modified, ctx.against, parsed.alpha);
|
|
80
|
-
}
|
|
81
|
-
lookupBase(name, ctx) {
|
|
82
|
-
if (name === AUTO_NAME) {
|
|
83
|
-
return ctx?.against ? contrastFor(ctx.against) : null;
|
|
84
|
-
}
|
|
85
|
-
return this.palette.get(name) ?? null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
//# sourceMappingURL=paletteResolver.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"paletteResolver.js","sourceRoot":"","sources":["../../src/themes/paletteResolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* hostStream — adapt a `TerminalHost` into the narrow Writable surface that
|
|
3
|
-
* Console (and Live) actually exercise.
|
|
4
|
-
*
|
|
5
|
-
* [LAW:types-are-the-program] The return type matches Console's `ConsoleSink`
|
|
6
|
-
* exactly: a single `.write(chunk)` method whose return value Console never
|
|
7
|
-
* inspects (so the type leaves it as `unknown`; this implementation happens
|
|
8
|
-
* to return `true` to mirror Node's stream contract, but callers may not
|
|
9
|
-
* rely on that). Anything wider would lie about what this adapter
|
|
10
|
-
* implements; anything narrower would force a cast at the call site.
|
|
11
|
-
* Calling `.pipe()`, `.cork()`, `.on('error')`, etc. is a programming error
|
|
12
|
-
* that TypeScript will reject at compile time.
|
|
13
|
-
*
|
|
14
|
-
* [LAW:locality-or-seam] Console + Live access their sink only via `.write()`
|
|
15
|
-
* — verified in src/core/console.ts (one `_file.write` call) and
|
|
16
|
-
* src/renderables/live.ts (every `this._console.file.write(...)` site). So
|
|
17
|
-
* this narrow surface is the entire contract they need.
|
|
18
|
-
*/
|
|
19
|
-
import type { ConsoleSink } from "../core/console.js";
|
|
20
|
-
import type { TerminalHost } from "./terminal-host.js";
|
|
21
|
-
/**
|
|
22
|
-
* Wrap a `TerminalHost` so its output can be threaded into `Console` via the
|
|
23
|
-
* existing `file:` option. The returned object implements `.write()` only —
|
|
24
|
-
* exactly the surface Console + Live touch.
|
|
25
|
-
*
|
|
26
|
-
* Pair with `forceTerminal: true` on the Console — without it, Console treats
|
|
27
|
-
* any non-undefined `file` option as non-TTY and disables color, which
|
|
28
|
-
* defeats the point.
|
|
29
|
-
*/
|
|
30
|
-
export declare function hostStream(host: TerminalHost): ConsoleSink;
|
|
31
|
-
//# sourceMappingURL=host-stream.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"host-stream.d.ts","sourceRoot":"","sources":["../../src/widgets/host-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,YAAY,GAAG,WAAW,CAO1D"}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* hostStream — adapt a `TerminalHost` into the narrow Writable surface that
|
|
3
|
-
* Console (and Live) actually exercise.
|
|
4
|
-
*
|
|
5
|
-
* [LAW:types-are-the-program] The return type matches Console's `ConsoleSink`
|
|
6
|
-
* exactly: a single `.write(chunk)` method whose return value Console never
|
|
7
|
-
* inspects (so the type leaves it as `unknown`; this implementation happens
|
|
8
|
-
* to return `true` to mirror Node's stream contract, but callers may not
|
|
9
|
-
* rely on that). Anything wider would lie about what this adapter
|
|
10
|
-
* implements; anything narrower would force a cast at the call site.
|
|
11
|
-
* Calling `.pipe()`, `.cork()`, `.on('error')`, etc. is a programming error
|
|
12
|
-
* that TypeScript will reject at compile time.
|
|
13
|
-
*
|
|
14
|
-
* [LAW:locality-or-seam] Console + Live access their sink only via `.write()`
|
|
15
|
-
* — verified in src/core/console.ts (one `_file.write` call) and
|
|
16
|
-
* src/renderables/live.ts (every `this._console.file.write(...)` site). So
|
|
17
|
-
* this narrow surface is the entire contract they need.
|
|
18
|
-
*/
|
|
19
|
-
/**
|
|
20
|
-
* Wrap a `TerminalHost` so its output can be threaded into `Console` via the
|
|
21
|
-
* existing `file:` option. The returned object implements `.write()` only —
|
|
22
|
-
* exactly the surface Console + Live touch.
|
|
23
|
-
*
|
|
24
|
-
* Pair with `forceTerminal: true` on the Console — without it, Console treats
|
|
25
|
-
* any non-undefined `file` option as non-TTY and disables color, which
|
|
26
|
-
* defeats the point.
|
|
27
|
-
*/
|
|
28
|
-
export function hostStream(host) {
|
|
29
|
-
return {
|
|
30
|
-
write(chunk) {
|
|
31
|
-
host.write(chunk);
|
|
32
|
-
return true;
|
|
33
|
-
},
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=host-stream.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"host-stream.js","sourceRoot":"","sources":["../../src/widgets/host-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAC,IAAkB;IAC3C,OAAO;QACL,KAAK,CAAC,KAA0B;YAC9B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAClB,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1,138 +0,0 @@
|
|
|
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`, on the `node/terminal-host`
|
|
10
|
-
* subpath) or a browser xterm.js terminal (`BrowserTerminalHost`, below).
|
|
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:one-way-deps] The interface and the browser host live here, in the
|
|
18
|
-
* barrel; the node host lives in `src/node/terminal-host.ts`, behind an
|
|
19
|
-
* explicit subpath, because it reads `process.stdin` / `process.stdout`. The
|
|
20
|
-
* dependency runs one way — the node adapter imports this seam; nothing here
|
|
21
|
-
* imports the adapter — so importing the main barrel in a browser cannot
|
|
22
|
-
* reach the ambient `process` global by any path, rather than merely not
|
|
23
|
-
* reaching it in practice. `test/seam/browser-safe.test.ts` is what holds
|
|
24
|
-
* that direction; who reads the host at all is `HOST_ACCESS` in
|
|
25
|
-
* `test/seam/ambient-process.ts`, and neither list is repeated here.
|
|
26
|
-
*
|
|
27
|
-
* [boundaries: capabilities over context] A `TerminalHost` grants exactly
|
|
28
|
-
* the I/O capabilities the runtime needs: write bytes, read input, query
|
|
29
|
-
* size, observe resize, switch raw mode, lifecycle. It is not an
|
|
30
|
-
* omniscient handle to "the process."
|
|
31
|
-
*/
|
|
32
|
-
import type { Unsubscribe } from "./types.js";
|
|
33
|
-
export interface TerminalSize {
|
|
34
|
-
readonly cols: number;
|
|
35
|
-
readonly rows: number;
|
|
36
|
-
}
|
|
37
|
-
export type DataHandler = (chunk: Uint8Array | string) => void;
|
|
38
|
-
export type ResizeHandler = (size: TerminalSize) => void;
|
|
39
|
-
export interface TerminalHost {
|
|
40
|
-
/**
|
|
41
|
-
* Write raw bytes (or UTF-8 text) to the terminal. The byte sequence is
|
|
42
|
-
* written verbatim; no escape interpretation, no framing.
|
|
43
|
-
*/
|
|
44
|
-
write(data: Uint8Array | string): void;
|
|
45
|
-
/**
|
|
46
|
-
* Subscribe to input data. The host emits whatever its underlying
|
|
47
|
-
* transport produces (Buffer on node, string on browser xterm.js); the
|
|
48
|
-
* runtime's parser accepts either.
|
|
49
|
-
*/
|
|
50
|
-
onData(handler: DataHandler): Unsubscribe;
|
|
51
|
-
/**
|
|
52
|
-
* Subscribe to terminal resize events. The handler fires with the new
|
|
53
|
-
* size after a resize is observed.
|
|
54
|
-
*/
|
|
55
|
-
onResize(handler: ResizeHandler): Unsubscribe;
|
|
56
|
-
/** Current terminal size in cells. Always returns a valid size. */
|
|
57
|
-
size(): TerminalSize;
|
|
58
|
-
/**
|
|
59
|
-
* Enable or disable raw mode on the input side. Implementations whose
|
|
60
|
-
* transport has no "cooked" mode (xterm.js, non-TTY pipes) silently
|
|
61
|
-
* no-op so callers don't need to branch on capability.
|
|
62
|
-
*/
|
|
63
|
-
setRawMode(raw: boolean): void;
|
|
64
|
-
/**
|
|
65
|
-
* Whether the host is connected to a real interactive terminal. Drives
|
|
66
|
-
* default option values (e.g. `manageCursor`, `manageRawMode`) in the
|
|
67
|
-
* runtime; non-TTY hosts default those features off.
|
|
68
|
-
*/
|
|
69
|
-
readonly isTTY: boolean;
|
|
70
|
-
/**
|
|
71
|
-
* Begin the host's lifecycle. Implementations attach whatever resources
|
|
72
|
-
* they own — or no-op when there is nothing to attach. Idempotent. See
|
|
73
|
-
* the concrete host's own JSDoc for what its `start()` actually does:
|
|
74
|
-
* `NodeTerminalHost` and `BrowserTerminalHost` both no-op because their
|
|
75
|
-
* underlying transports (process streams; a caller-managed xterm.js
|
|
76
|
-
* Terminal) are already live by the time the host is constructed.
|
|
77
|
-
*/
|
|
78
|
-
start(): void;
|
|
79
|
-
/**
|
|
80
|
-
* Stop the host's lifecycle. Pairs with `start`. Idempotent. After
|
|
81
|
-
* `stop()`, the host releases its own subscriptions to the underlying
|
|
82
|
-
* transport and clears its handler sets; the transport itself is not
|
|
83
|
-
* torn down (that is the caller's concern — process streams persist;
|
|
84
|
-
* an xterm.js Terminal is disposed by the caller). Re-subscribing via
|
|
85
|
-
* `onData` / `onResize` after `stop()` re-engages the host.
|
|
86
|
-
*/
|
|
87
|
-
stop(): void;
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* Subset of xterm.js's `Terminal` surface the browser host depends on.
|
|
91
|
-
*
|
|
92
|
-
* [LAW:locality-or-seam] Declaring the dependency by *shape* — rather than
|
|
93
|
-
* importing xterm.js's types — keeps this package free of an xterm.js
|
|
94
|
-
* dev-dep at the type level, lets the browser-bundle pipeline (downstream
|
|
95
|
-
* ticket) pin whichever xterm.js version it wants, and lets unit tests
|
|
96
|
-
* pass a hand-built fake: ask for exactly the capabilities the host uses,
|
|
97
|
-
* no more.
|
|
98
|
-
*/
|
|
99
|
-
export interface XtermDisposable {
|
|
100
|
-
dispose(): void;
|
|
101
|
-
}
|
|
102
|
-
export interface XtermResizeEvent {
|
|
103
|
-
cols: number;
|
|
104
|
-
rows: number;
|
|
105
|
-
}
|
|
106
|
-
export interface XtermTerminal {
|
|
107
|
-
readonly cols: number;
|
|
108
|
-
readonly rows: number;
|
|
109
|
-
write(data: Uint8Array | string): void;
|
|
110
|
-
onData(handler: (data: string) => void): XtermDisposable;
|
|
111
|
-
onResize(handler: (size: XtermResizeEvent) => void): XtermDisposable;
|
|
112
|
-
}
|
|
113
|
-
export interface BrowserTerminalHostOptions {
|
|
114
|
-
/**
|
|
115
|
-
* The xterm.js `Terminal` instance to wrap. The caller is responsible
|
|
116
|
-
* for its DOM lifecycle (`terminal.open(element)`, `terminal.dispose()`)
|
|
117
|
-
* — the host only owns its own subscriber lifecycle, exactly mirroring
|
|
118
|
-
* `NodeTerminalHost`'s relationship to `process.stdin`/`process.stdout`.
|
|
119
|
-
*/
|
|
120
|
-
terminal: XtermTerminal;
|
|
121
|
-
}
|
|
122
|
-
export declare class BrowserTerminalHost implements TerminalHost {
|
|
123
|
-
private readonly terminal;
|
|
124
|
-
private readonly dataHandlers;
|
|
125
|
-
private readonly resizeHandlers;
|
|
126
|
-
private dataSubscription;
|
|
127
|
-
private resizeSubscription;
|
|
128
|
-
constructor(options: BrowserTerminalHostOptions);
|
|
129
|
-
get isTTY(): boolean;
|
|
130
|
-
write(data: Uint8Array | string): void;
|
|
131
|
-
size(): TerminalSize;
|
|
132
|
-
setRawMode(_raw: boolean): void;
|
|
133
|
-
onData(handler: DataHandler): Unsubscribe;
|
|
134
|
-
onResize(handler: ResizeHandler): Unsubscribe;
|
|
135
|
-
start(): void;
|
|
136
|
-
stop(): void;
|
|
137
|
-
}
|
|
138
|
-
//# sourceMappingURL=terminal-host.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-host.d.ts","sourceRoot":"","sources":["../../src/widgets/terminal-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAS9C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,WAAW,GAAG,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,KAAK,IAAI,CAAC;AAC/D,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;AAEzD,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;IAEvC;;;;OAIG;IACH,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,CAAC;IAE1C;;;OAGG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW,CAAC;IAE9C,mEAAmE;IACnE,IAAI,IAAI,YAAY,CAAC;IAErB;;;;OAIG;IACH,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAE/B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAExB;;;;;;;OAOG;IACH,KAAK,IAAI,IAAI,CAAC;IAEd;;;;;;;OAOG;IACH,IAAI,IAAI,IAAI,CAAC;CACd;AAMD;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI,CAAC;IACvC,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,eAAe,CAAC;IACzD,QAAQ,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAAG,eAAe,CAAC;CACtE;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,QAAQ,EAAE,aAAa,CAAC;CACzB;AAED,qBAAa,mBAAoB,YAAW,YAAY;IACtD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAA0B;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA4B;IAC3D,OAAO,CAAC,gBAAgB,CAA8B;IACtD,OAAO,CAAC,kBAAkB,CAA8B;gBAE5C,OAAO,EAAE,0BAA0B;IAQ/C,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,GAAG,IAAI;IAItC,IAAI,IAAI,YAAY;IAUpB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAO/B,MAAM,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW;IAgBzC,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,WAAW;IAiB7C,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,IAAI;CAmBb"}
|
|
@@ -1,127 +0,0 @@
|
|
|
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`, on the `node/terminal-host`
|
|
10
|
-
* subpath) or a browser xterm.js terminal (`BrowserTerminalHost`, below).
|
|
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:one-way-deps] The interface and the browser host live here, in the
|
|
18
|
-
* barrel; the node host lives in `src/node/terminal-host.ts`, behind an
|
|
19
|
-
* explicit subpath, because it reads `process.stdin` / `process.stdout`. The
|
|
20
|
-
* dependency runs one way — the node adapter imports this seam; nothing here
|
|
21
|
-
* imports the adapter — so importing the main barrel in a browser cannot
|
|
22
|
-
* reach the ambient `process` global by any path, rather than merely not
|
|
23
|
-
* reaching it in practice. `test/seam/browser-safe.test.ts` is what holds
|
|
24
|
-
* that direction; who reads the host at all is `HOST_ACCESS` in
|
|
25
|
-
* `test/seam/ambient-process.ts`, and neither list is repeated here.
|
|
26
|
-
*
|
|
27
|
-
* [boundaries: capabilities over context] A `TerminalHost` grants exactly
|
|
28
|
-
* the I/O capabilities the runtime needs: write bytes, read input, query
|
|
29
|
-
* size, observe resize, switch raw mode, lifecycle. It is not an
|
|
30
|
-
* omniscient handle to "the process."
|
|
31
|
-
*/
|
|
32
|
-
export class BrowserTerminalHost {
|
|
33
|
-
terminal;
|
|
34
|
-
dataHandlers = new Set();
|
|
35
|
-
resizeHandlers = new Set();
|
|
36
|
-
dataSubscription;
|
|
37
|
-
resizeSubscription;
|
|
38
|
-
constructor(options) {
|
|
39
|
-
this.terminal = options.terminal;
|
|
40
|
-
}
|
|
41
|
-
// [LAW:dataflow-not-control-flow] xterm.js is always an interactive
|
|
42
|
-
// terminal — there is no "non-TTY" code path in the browser. The
|
|
43
|
-
// runtime never branches on the value; this is the only sensible
|
|
44
|
-
// constant for this host.
|
|
45
|
-
get isTTY() {
|
|
46
|
-
return true;
|
|
47
|
-
}
|
|
48
|
-
write(data) {
|
|
49
|
-
this.terminal.write(data);
|
|
50
|
-
}
|
|
51
|
-
size() {
|
|
52
|
-
return { cols: this.terminal.cols, rows: this.terminal.rows };
|
|
53
|
-
}
|
|
54
|
-
// [LAW:dataflow-not-control-flow] xterm.js delivers keystrokes raw
|
|
55
|
-
// unconditionally — there is no cooked mode to toggle. The no-op
|
|
56
|
-
// matches the TerminalHost contract's documented "silently no-op when
|
|
57
|
-
// the transport has no cooked mode," so callers stay uniform across
|
|
58
|
-
// hosts. (Mirror: NodeTerminalHost on a non-TTY stream takes the same
|
|
59
|
-
// no-op path via the optional-chain in `applyRawMode`.)
|
|
60
|
-
setRawMode(_raw) { }
|
|
61
|
-
// [LAW:single-enforcer] One underlying `terminal.onData` subscription
|
|
62
|
-
// fans out to every host-level handler — the same lazy-attach,
|
|
63
|
-
// last-unsubscribe-detaches shape as NodeTerminalHost.onData. The
|
|
64
|
-
// runtime never sees the underlying subscription; it sees a single
|
|
65
|
-
// uniform `(handler) => Unsubscribe` API across hosts.
|
|
66
|
-
onData(handler) {
|
|
67
|
-
this.dataHandlers.add(handler);
|
|
68
|
-
if (!this.dataSubscription) {
|
|
69
|
-
this.dataSubscription = this.terminal.onData((chunk) => {
|
|
70
|
-
for (const h of this.dataHandlers)
|
|
71
|
-
h(chunk);
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
return () => {
|
|
75
|
-
this.dataHandlers.delete(handler);
|
|
76
|
-
if (this.dataHandlers.size === 0 && this.dataSubscription) {
|
|
77
|
-
this.dataSubscription.dispose();
|
|
78
|
-
this.dataSubscription = undefined;
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
onResize(handler) {
|
|
83
|
-
this.resizeHandlers.add(handler);
|
|
84
|
-
if (!this.resizeSubscription) {
|
|
85
|
-
this.resizeSubscription = this.terminal.onResize((size) => {
|
|
86
|
-
const snapshot = { cols: size.cols, rows: size.rows };
|
|
87
|
-
for (const h of this.resizeHandlers)
|
|
88
|
-
h(snapshot);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return () => {
|
|
92
|
-
this.resizeHandlers.delete(handler);
|
|
93
|
-
if (this.resizeHandlers.size === 0 && this.resizeSubscription) {
|
|
94
|
-
this.resizeSubscription.dispose();
|
|
95
|
-
this.resizeSubscription = undefined;
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
start() {
|
|
100
|
-
// [LAW:one-source-of-truth] The host does NOT own the terminal's DOM
|
|
101
|
-
// lifecycle (`terminal.open` / `terminal.dispose`). That is the
|
|
102
|
-
// caller's responsibility, exactly as NodeTerminalHost does not own
|
|
103
|
-
// `process.stdin`/`process.stdout`. start() is here so the runtime
|
|
104
|
-
// can call it uniformly across hosts; for this host there is
|
|
105
|
-
// nothing to do at this seam.
|
|
106
|
-
}
|
|
107
|
-
stop() {
|
|
108
|
-
// [LAW:one-source-of-truth] Symmetric teardown mirroring
|
|
109
|
-
// NodeTerminalHost.stop: drop every host-level subscriber and
|
|
110
|
-
// dispose the underlying terminal subscriptions. The terminal
|
|
111
|
-
// itself stays alive — re-subscribing via onData/onResize after
|
|
112
|
-
// stop() works, since the lazy-attach path re-creates the
|
|
113
|
-
// subscription on next subscribe. Calling stop() repeatedly is
|
|
114
|
-
// safe — the subscription guards make later calls no-ops.
|
|
115
|
-
if (this.dataSubscription) {
|
|
116
|
-
this.dataSubscription.dispose();
|
|
117
|
-
this.dataSubscription = undefined;
|
|
118
|
-
}
|
|
119
|
-
if (this.resizeSubscription) {
|
|
120
|
-
this.resizeSubscription.dispose();
|
|
121
|
-
this.resizeSubscription = undefined;
|
|
122
|
-
}
|
|
123
|
-
this.dataHandlers.clear();
|
|
124
|
-
this.resizeHandlers.clear();
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
//# sourceMappingURL=terminal-host.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-host.js","sourceRoot":"","sources":["../../src/widgets/terminal-host.ts"],"names":[],"mappings":"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"}
|