restty 0.1.21 → 0.1.23
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 +85 -0
- package/dist/app/clipboard-paste.d.ts +5 -0
- package/dist/app/index.d.ts +3 -2
- package/dist/app/restty.d.ts +201 -0
- package/dist/app/types.d.ts +21 -0
- package/dist/{chunk-ym658zhj.js → chunk-mkkhfg0z.js} +970 -40
- package/dist/index.d.ts +2 -2
- package/dist/input/output.d.ts +10 -1
- package/dist/input/types.d.ts +2 -0
- package/dist/internal.js +1 -1
- package/dist/restty.js +4 -2
- package/dist/xterm.d.ts +77 -0
- package/dist/xterm.js +254 -0
- package/package.json +6 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Restty, ResttyPaneHandle, createRestty } from "./app/restty";
|
|
2
|
-
export type { ResttyOptions, ResttyPaneApi } from "./app/restty";
|
|
1
|
+
export { RESTTY_PLUGIN_API_VERSION, Restty, ResttyPaneHandle, createRestty } from "./app/restty";
|
|
2
|
+
export type { ResttyOptions, ResttyPaneApi, ResttyPluginApiRange, ResttyPlugin, ResttyPluginCleanup, ResttyPluginContext, ResttyPluginDisposable, ResttyPluginEvents, ResttyPluginInfo, ResttyPluginRequires, ResttyInputInterceptor, ResttyInputInterceptorPayload, ResttyInterceptorOptions, ResttyLifecycleHook, ResttyLifecycleHookPayload, ResttyPluginLoadResult, ResttyPluginLoadStatus, ResttyPluginManifestEntry, ResttyPluginRegistry, ResttyPluginRegistryEntry, ResttyRenderHook, ResttyRenderHookPayload, ResttyOutputInterceptor, ResttyOutputInterceptorPayload, } from "./app/restty";
|
|
3
3
|
export { getBuiltinTheme, getBuiltinThemeSource, isBuiltinThemeName, listBuiltinThemeNames, parseGhosttyTheme, } from "./theme";
|
|
4
4
|
export type { GhosttyTheme, ResttyBuiltinThemeName } from "./theme";
|
|
5
5
|
export type { ResttyFontSource, ResttyUrlFontSource, ResttyBufferFontSource, ResttyLocalFontSource, ResttyFontPreset, } from "./app/types";
|
package/dist/input/output.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CursorPosition, WindowOp } from "./types";
|
|
1
|
+
import type { CellPosition, CursorPosition, WindowOp } from "./types";
|
|
2
2
|
import type { MouseController } from "./mouse";
|
|
3
3
|
/**
|
|
4
4
|
* Construction options for OutputFilter.
|
|
@@ -50,6 +50,10 @@ export declare class OutputFilter {
|
|
|
50
50
|
private clipboardWrite?;
|
|
51
51
|
private clipboardRead?;
|
|
52
52
|
private getDefaultColors?;
|
|
53
|
+
private semanticPromptSeen;
|
|
54
|
+
private promptClickEvents;
|
|
55
|
+
private promptInputActive;
|
|
56
|
+
private commandRunning;
|
|
53
57
|
constructor(options: OutputFilterOptions);
|
|
54
58
|
setCursorProvider(fn: () => CursorPosition): void;
|
|
55
59
|
setReplySink(fn: (data: string) => void): void;
|
|
@@ -58,6 +62,11 @@ export declare class OutputFilter {
|
|
|
58
62
|
isBracketedPaste(): boolean;
|
|
59
63
|
isFocusReporting(): boolean;
|
|
60
64
|
isSynchronizedOutput(): boolean;
|
|
65
|
+
isPromptClickEventsEnabled(): boolean;
|
|
66
|
+
encodePromptClickEvent(cell: CellPosition): string;
|
|
67
|
+
private readOsc133BoolOption;
|
|
68
|
+
private observeSemanticPromptOsc;
|
|
69
|
+
private observeOsc;
|
|
61
70
|
private replyOscColor;
|
|
62
71
|
private handleOsc;
|
|
63
72
|
private handleModeSeq;
|
package/dist/input/types.d.ts
CHANGED
|
@@ -160,6 +160,8 @@ export type InputHandler = {
|
|
|
160
160
|
isFocusReporting: () => boolean;
|
|
161
161
|
isAltScreen: () => boolean;
|
|
162
162
|
isSynchronizedOutput: () => boolean;
|
|
163
|
+
isPromptClickEventsEnabled: () => boolean;
|
|
164
|
+
encodePromptClickEvent: (cell: CellPosition) => string;
|
|
163
165
|
/**
|
|
164
166
|
* Encode pointer input as terminal mouse events (SGR).
|
|
165
167
|
*/
|
package/dist/internal.js
CHANGED
package/dist/restty.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
RESTTY_PLUGIN_API_VERSION,
|
|
2
3
|
Restty,
|
|
3
4
|
ResttyPaneHandle,
|
|
4
5
|
createRestty,
|
|
@@ -7,7 +8,7 @@ import {
|
|
|
7
8
|
isBuiltinThemeName,
|
|
8
9
|
listBuiltinThemeNames,
|
|
9
10
|
parseGhosttyTheme
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-mkkhfg0z.js";
|
|
11
12
|
export {
|
|
12
13
|
parseGhosttyTheme,
|
|
13
14
|
listBuiltinThemeNames,
|
|
@@ -16,5 +17,6 @@ export {
|
|
|
16
17
|
getBuiltinTheme,
|
|
17
18
|
createRestty,
|
|
18
19
|
ResttyPaneHandle,
|
|
19
|
-
Restty
|
|
20
|
+
Restty,
|
|
21
|
+
RESTTY_PLUGIN_API_VERSION
|
|
20
22
|
};
|
package/dist/xterm.d.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { type Restty, type ResttyOptions } from "./app/restty";
|
|
2
|
+
export type IDisposable = {
|
|
3
|
+
dispose: () => void;
|
|
4
|
+
};
|
|
5
|
+
export type TerminalResizeEvent = {
|
|
6
|
+
cols: number;
|
|
7
|
+
rows: number;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Subset of xterm.js addon contract supported by the restty compatibility layer.
|
|
11
|
+
*/
|
|
12
|
+
export type TerminalAddon = {
|
|
13
|
+
activate: (terminal: Terminal) => void;
|
|
14
|
+
dispose: () => void;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Options for the xterm compatibility terminal.
|
|
18
|
+
*
|
|
19
|
+
* `root` is intentionally omitted because xterm-style flow mounts via `open(element)`.
|
|
20
|
+
* Additional unknown keys are accepted for migration ergonomics and kept in
|
|
21
|
+
* the terminal option bag, but are not forwarded to restty internals.
|
|
22
|
+
*/
|
|
23
|
+
export type TerminalOptions = Omit<ResttyOptions, "root"> & {
|
|
24
|
+
cols?: number;
|
|
25
|
+
rows?: number;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* xterm.js-style compatibility wrapper backed by `Restty`.
|
|
30
|
+
*
|
|
31
|
+
* This intentionally implements a focused subset needed for migration.
|
|
32
|
+
*/
|
|
33
|
+
export declare class Terminal {
|
|
34
|
+
private readonly resttyOptionsBase;
|
|
35
|
+
private readonly userAppOptions;
|
|
36
|
+
private readonly addons;
|
|
37
|
+
private readonly pendingOutput;
|
|
38
|
+
private readonly dataListeners;
|
|
39
|
+
private readonly resizeListeners;
|
|
40
|
+
private readonly optionValues;
|
|
41
|
+
private resttyInstance;
|
|
42
|
+
private elementRef;
|
|
43
|
+
private disposed;
|
|
44
|
+
private opened;
|
|
45
|
+
private pendingSize;
|
|
46
|
+
cols: number;
|
|
47
|
+
rows: number;
|
|
48
|
+
constructor(options?: TerminalOptions);
|
|
49
|
+
/** Mounted root passed to `open`, null before mount/dispose. */
|
|
50
|
+
get element(): HTMLElement | null;
|
|
51
|
+
/** Underlying restty instance after `open`, null otherwise. */
|
|
52
|
+
get restty(): Restty | null;
|
|
53
|
+
/** xterm-like option bag (compat-focused subset). */
|
|
54
|
+
get options(): Record<string, unknown>;
|
|
55
|
+
set options(next: Record<string, unknown>);
|
|
56
|
+
open(parent: HTMLElement): void;
|
|
57
|
+
write(data: string, callback?: () => void): void;
|
|
58
|
+
writeln(data?: string, callback?: () => void): void;
|
|
59
|
+
resize(cols: number, rows: number): void;
|
|
60
|
+
focus(): void;
|
|
61
|
+
blur(): void;
|
|
62
|
+
clear(): void;
|
|
63
|
+
reset(): void;
|
|
64
|
+
onData(listener: (data: string) => void): IDisposable;
|
|
65
|
+
onResize(listener: (size: TerminalResizeEvent) => void): IDisposable;
|
|
66
|
+
setOption(key: string, value: unknown): void;
|
|
67
|
+
getOption(key: string): unknown;
|
|
68
|
+
loadAddon(addon: TerminalAddon): void;
|
|
69
|
+
dispose(): void;
|
|
70
|
+
private ensureUsable;
|
|
71
|
+
private applyOptions;
|
|
72
|
+
private createCompatAppOptions;
|
|
73
|
+
private emitData;
|
|
74
|
+
private emitResize;
|
|
75
|
+
private addListener;
|
|
76
|
+
private normalizeDimension;
|
|
77
|
+
}
|
package/dist/xterm.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createRestty
|
|
3
|
+
} from "./chunk-mkkhfg0z.js";
|
|
4
|
+
|
|
5
|
+
// src/xterm.ts
|
|
6
|
+
class Terminal {
|
|
7
|
+
resttyOptionsBase;
|
|
8
|
+
userAppOptions;
|
|
9
|
+
addons = new Set;
|
|
10
|
+
pendingOutput = [];
|
|
11
|
+
dataListeners = new Set;
|
|
12
|
+
resizeListeners = new Set;
|
|
13
|
+
optionValues;
|
|
14
|
+
resttyInstance = null;
|
|
15
|
+
elementRef = null;
|
|
16
|
+
disposed = false;
|
|
17
|
+
opened = false;
|
|
18
|
+
pendingSize = null;
|
|
19
|
+
cols;
|
|
20
|
+
rows;
|
|
21
|
+
constructor(options = {}) {
|
|
22
|
+
const { cols, rows, appOptions, ...resttyOptionsBase } = options;
|
|
23
|
+
this.resttyOptionsBase = resttyOptionsBase;
|
|
24
|
+
this.userAppOptions = appOptions;
|
|
25
|
+
this.optionValues = { ...options };
|
|
26
|
+
delete this.optionValues.cols;
|
|
27
|
+
delete this.optionValues.rows;
|
|
28
|
+
this.cols = this.normalizeDimension(cols, 80);
|
|
29
|
+
this.rows = this.normalizeDimension(rows, 24);
|
|
30
|
+
if (Number.isFinite(cols) && Number.isFinite(rows)) {
|
|
31
|
+
this.pendingSize = { cols: this.cols, rows: this.rows };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
get element() {
|
|
35
|
+
return this.elementRef;
|
|
36
|
+
}
|
|
37
|
+
get restty() {
|
|
38
|
+
return this.resttyInstance;
|
|
39
|
+
}
|
|
40
|
+
get options() {
|
|
41
|
+
return {
|
|
42
|
+
...this.optionValues,
|
|
43
|
+
cols: this.cols,
|
|
44
|
+
rows: this.rows
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
set options(next) {
|
|
48
|
+
this.ensureUsable();
|
|
49
|
+
this.applyOptions(next);
|
|
50
|
+
}
|
|
51
|
+
open(parent) {
|
|
52
|
+
this.ensureUsable();
|
|
53
|
+
if (this.opened) {
|
|
54
|
+
throw new Error("xterm compatibility Terminal is already opened");
|
|
55
|
+
}
|
|
56
|
+
this.opened = true;
|
|
57
|
+
this.elementRef = parent;
|
|
58
|
+
this.resttyInstance = createRestty({
|
|
59
|
+
...this.resttyOptionsBase,
|
|
60
|
+
appOptions: this.createCompatAppOptions(),
|
|
61
|
+
root: parent
|
|
62
|
+
});
|
|
63
|
+
if (this.pendingSize) {
|
|
64
|
+
this.resttyInstance.resize(this.pendingSize.cols, this.pendingSize.rows);
|
|
65
|
+
}
|
|
66
|
+
if (this.pendingOutput.length > 0) {
|
|
67
|
+
for (let i = 0;i < this.pendingOutput.length; i += 1) {
|
|
68
|
+
this.resttyInstance.sendInput(this.pendingOutput[i], "pty");
|
|
69
|
+
}
|
|
70
|
+
this.pendingOutput.length = 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
write(data, callback) {
|
|
74
|
+
this.ensureUsable();
|
|
75
|
+
if (!data) {
|
|
76
|
+
callback?.();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (this.resttyInstance) {
|
|
80
|
+
this.resttyInstance.sendInput(data, "pty");
|
|
81
|
+
} else {
|
|
82
|
+
this.pendingOutput.push(data);
|
|
83
|
+
}
|
|
84
|
+
callback?.();
|
|
85
|
+
}
|
|
86
|
+
writeln(data = "", callback) {
|
|
87
|
+
this.write(`${data}\r
|
|
88
|
+
`, callback);
|
|
89
|
+
}
|
|
90
|
+
resize(cols, rows) {
|
|
91
|
+
this.ensureUsable();
|
|
92
|
+
const next = {
|
|
93
|
+
cols: this.normalizeDimension(cols, this.cols),
|
|
94
|
+
rows: this.normalizeDimension(rows, this.rows)
|
|
95
|
+
};
|
|
96
|
+
this.cols = next.cols;
|
|
97
|
+
this.rows = next.rows;
|
|
98
|
+
this.pendingSize = next;
|
|
99
|
+
this.resttyInstance?.resize(next.cols, next.rows);
|
|
100
|
+
this.emitResize(next);
|
|
101
|
+
}
|
|
102
|
+
focus() {
|
|
103
|
+
if (this.disposed)
|
|
104
|
+
return;
|
|
105
|
+
this.resttyInstance?.focus();
|
|
106
|
+
}
|
|
107
|
+
blur() {
|
|
108
|
+
if (this.disposed)
|
|
109
|
+
return;
|
|
110
|
+
this.resttyInstance?.blur();
|
|
111
|
+
}
|
|
112
|
+
clear() {
|
|
113
|
+
this.ensureUsable();
|
|
114
|
+
if (this.resttyInstance) {
|
|
115
|
+
this.resttyInstance.clearScreen();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
this.pendingOutput.length = 0;
|
|
119
|
+
}
|
|
120
|
+
reset() {
|
|
121
|
+
this.ensureUsable();
|
|
122
|
+
this.clear();
|
|
123
|
+
if (this.resttyInstance) {
|
|
124
|
+
this.resttyInstance.sendInput("\x1Bc", "pty");
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
onData(listener) {
|
|
128
|
+
this.ensureUsable();
|
|
129
|
+
return this.addListener(this.dataListeners, listener);
|
|
130
|
+
}
|
|
131
|
+
onResize(listener) {
|
|
132
|
+
this.ensureUsable();
|
|
133
|
+
return this.addListener(this.resizeListeners, listener);
|
|
134
|
+
}
|
|
135
|
+
setOption(key, value) {
|
|
136
|
+
this.ensureUsable();
|
|
137
|
+
this.applyOptions({ [key]: value });
|
|
138
|
+
}
|
|
139
|
+
getOption(key) {
|
|
140
|
+
if (key === "cols")
|
|
141
|
+
return this.cols;
|
|
142
|
+
if (key === "rows")
|
|
143
|
+
return this.rows;
|
|
144
|
+
return this.optionValues[key];
|
|
145
|
+
}
|
|
146
|
+
loadAddon(addon) {
|
|
147
|
+
this.ensureUsable();
|
|
148
|
+
if (!addon || typeof addon.activate !== "function" || typeof addon.dispose !== "function") {
|
|
149
|
+
throw new Error("xterm compatibility addon must define activate() and dispose()");
|
|
150
|
+
}
|
|
151
|
+
if (this.addons.has(addon))
|
|
152
|
+
return;
|
|
153
|
+
addon.activate(this);
|
|
154
|
+
this.addons.add(addon);
|
|
155
|
+
}
|
|
156
|
+
dispose() {
|
|
157
|
+
if (this.disposed)
|
|
158
|
+
return;
|
|
159
|
+
this.disposed = true;
|
|
160
|
+
const addons = Array.from(this.addons);
|
|
161
|
+
this.addons.clear();
|
|
162
|
+
for (let i = 0;i < addons.length; i += 1) {
|
|
163
|
+
try {
|
|
164
|
+
addons[i].dispose();
|
|
165
|
+
} catch {}
|
|
166
|
+
}
|
|
167
|
+
this.pendingOutput.length = 0;
|
|
168
|
+
this.pendingSize = null;
|
|
169
|
+
this.opened = false;
|
|
170
|
+
this.elementRef = null;
|
|
171
|
+
this.dataListeners.clear();
|
|
172
|
+
this.resizeListeners.clear();
|
|
173
|
+
if (this.resttyInstance) {
|
|
174
|
+
this.resttyInstance.destroy();
|
|
175
|
+
this.resttyInstance = null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
ensureUsable() {
|
|
179
|
+
if (this.disposed) {
|
|
180
|
+
throw new Error("xterm compatibility Terminal is disposed");
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
applyOptions(next) {
|
|
184
|
+
const hasCols = Object.prototype.hasOwnProperty.call(next, "cols");
|
|
185
|
+
const hasRows = Object.prototype.hasOwnProperty.call(next, "rows");
|
|
186
|
+
if (hasCols || hasRows) {
|
|
187
|
+
const cols = hasCols ? this.normalizeDimension(next.cols, this.cols) : this.cols;
|
|
188
|
+
const rows = hasRows ? this.normalizeDimension(next.rows, this.rows) : this.rows;
|
|
189
|
+
this.resize(cols, rows);
|
|
190
|
+
}
|
|
191
|
+
const keys = Object.keys(next);
|
|
192
|
+
for (let i = 0;i < keys.length; i += 1) {
|
|
193
|
+
const key = keys[i];
|
|
194
|
+
if (key === "cols" || key === "rows")
|
|
195
|
+
continue;
|
|
196
|
+
this.optionValues[key] = next[key];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
createCompatAppOptions() {
|
|
200
|
+
return (context) => {
|
|
201
|
+
const resolved = typeof this.userAppOptions === "function" ? this.userAppOptions(context) : this.userAppOptions ?? {};
|
|
202
|
+
const userBeforeInput = resolved.beforeInput;
|
|
203
|
+
return {
|
|
204
|
+
...resolved,
|
|
205
|
+
beforeInput: ({ text, source }) => {
|
|
206
|
+
const maybeNext = userBeforeInput?.({ text, source });
|
|
207
|
+
if (maybeNext === null)
|
|
208
|
+
return null;
|
|
209
|
+
const nextText = maybeNext === undefined ? text : maybeNext;
|
|
210
|
+
if (source !== "pty" && nextText) {
|
|
211
|
+
this.emitData(nextText);
|
|
212
|
+
}
|
|
213
|
+
return nextText;
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
emitData(data) {
|
|
219
|
+
const listeners = Array.from(this.dataListeners);
|
|
220
|
+
for (let i = 0;i < listeners.length; i += 1) {
|
|
221
|
+
try {
|
|
222
|
+
listeners[i](data);
|
|
223
|
+
} catch (error) {
|
|
224
|
+
console.error("[restty/xterm] onData listener error:", error);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
emitResize(size) {
|
|
229
|
+
const listeners = Array.from(this.resizeListeners);
|
|
230
|
+
for (let i = 0;i < listeners.length; i += 1) {
|
|
231
|
+
try {
|
|
232
|
+
listeners[i](size);
|
|
233
|
+
} catch (error) {
|
|
234
|
+
console.error("[restty/xterm] onResize listener error:", error);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
addListener(bucket, listener) {
|
|
239
|
+
bucket.add(listener);
|
|
240
|
+
return {
|
|
241
|
+
dispose: () => {
|
|
242
|
+
bucket.delete(listener);
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
normalizeDimension(value, fallback) {
|
|
247
|
+
if (!Number.isFinite(value) || value <= 0)
|
|
248
|
+
return fallback;
|
|
249
|
+
return Math.max(1, Math.trunc(value));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
export {
|
|
253
|
+
Terminal
|
|
254
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "restty",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "Browser terminal rendering library powered by WASM, WebGPU/WebGL2, and TypeScript text shaping.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"terminal",
|
|
@@ -46,6 +46,11 @@
|
|
|
46
46
|
"types": "./dist/internal.d.ts",
|
|
47
47
|
"import": "./dist/internal.js",
|
|
48
48
|
"default": "./dist/internal.js"
|
|
49
|
+
},
|
|
50
|
+
"./xterm": {
|
|
51
|
+
"types": "./dist/xterm.d.ts",
|
|
52
|
+
"import": "./dist/xterm.js",
|
|
53
|
+
"default": "./dist/xterm.js"
|
|
49
54
|
}
|
|
50
55
|
},
|
|
51
56
|
"scripts": {
|