restty 0.1.21 → 0.1.22
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-d3xkkgrb.js} +842 -34
- package/dist/index.d.ts +2 -2
- 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
|
@@ -26723,6 +26723,17 @@ function buildFontAtlasIfNeeded(params) {
|
|
|
26723
26723
|
};
|
|
26724
26724
|
}
|
|
26725
26725
|
|
|
26726
|
+
// src/app/clipboard-paste.ts
|
|
26727
|
+
function readPastePayloadFromDataTransfer(dataTransfer) {
|
|
26728
|
+
if (!dataTransfer)
|
|
26729
|
+
return null;
|
|
26730
|
+
const text = dataTransfer.getData("text/plain") || "";
|
|
26731
|
+
return text ? {
|
|
26732
|
+
kind: "text",
|
|
26733
|
+
text
|
|
26734
|
+
} : null;
|
|
26735
|
+
}
|
|
26736
|
+
|
|
26726
26737
|
// src/app/font-sources.ts
|
|
26727
26738
|
var DEFAULT_FONT_SOURCES = [
|
|
26728
26739
|
{
|
|
@@ -50315,6 +50326,8 @@ var DEFAULT_EMOJI_CONSTRAINT = {
|
|
|
50315
50326
|
};
|
|
50316
50327
|
function createResttyApp(options) {
|
|
50317
50328
|
const { canvas: canvasInput, imeInput: imeInputInput, elements, callbacks } = options;
|
|
50329
|
+
const beforeInputHook = options.beforeInput;
|
|
50330
|
+
const beforeRenderOutputHook = options.beforeRenderOutput;
|
|
50318
50331
|
const session = options.session ?? getDefaultResttyAppSession();
|
|
50319
50332
|
const textShaper = exports_dist;
|
|
50320
50333
|
if (!canvasInput) {
|
|
@@ -51593,15 +51606,18 @@ function createResttyApp(options) {
|
|
|
51593
51606
|
function sendKeyInput(text, source = "key") {
|
|
51594
51607
|
if (!text)
|
|
51595
51608
|
return;
|
|
51609
|
+
const intercepted = runBeforeInputHook(text, source);
|
|
51610
|
+
if (!intercepted)
|
|
51611
|
+
return;
|
|
51596
51612
|
if (source !== "program" && (selectionState.active || selectionState.dragging)) {
|
|
51597
51613
|
clearSelection();
|
|
51598
51614
|
}
|
|
51599
51615
|
if (ptyTransport.isConnected()) {
|
|
51600
|
-
const payload = inputHandler.mapKeyForPty(
|
|
51616
|
+
const payload = inputHandler.mapKeyForPty(intercepted);
|
|
51601
51617
|
ptyTransport.sendInput(payload);
|
|
51602
51618
|
return;
|
|
51603
51619
|
}
|
|
51604
|
-
sendInput(
|
|
51620
|
+
sendInput(intercepted, source, { skipHooks: true });
|
|
51605
51621
|
}
|
|
51606
51622
|
function formatPasteText(text) {
|
|
51607
51623
|
if (!inputHandler?.isBracketedPaste?.())
|
|
@@ -51613,6 +51629,13 @@ function createResttyApp(options) {
|
|
|
51613
51629
|
return;
|
|
51614
51630
|
sendKeyInput(formatPasteText(text));
|
|
51615
51631
|
}
|
|
51632
|
+
function sendPastePayloadFromDataTransfer(dataTransfer) {
|
|
51633
|
+
const payload = readPastePayloadFromDataTransfer(dataTransfer);
|
|
51634
|
+
if (!payload)
|
|
51635
|
+
return false;
|
|
51636
|
+
sendPasteText(payload.text);
|
|
51637
|
+
return true;
|
|
51638
|
+
}
|
|
51616
51639
|
function openLink(uri) {
|
|
51617
51640
|
if (!uri || typeof window === "undefined")
|
|
51618
51641
|
return;
|
|
@@ -51911,13 +51934,16 @@ function createResttyApp(options) {
|
|
|
51911
51934
|
if (imeState.composing)
|
|
51912
51935
|
return;
|
|
51913
51936
|
if (event.inputType === "insertFromPaste") {
|
|
51937
|
+
event.preventDefault();
|
|
51938
|
+
suppressNextInput = true;
|
|
51914
51939
|
const pasteText = event.dataTransfer?.getData("text/plain") || event.data || "";
|
|
51915
51940
|
if (pasteText) {
|
|
51916
|
-
event.preventDefault();
|
|
51917
|
-
suppressNextInput = true;
|
|
51918
51941
|
sendPasteText(pasteText);
|
|
51919
51942
|
imeInput.value = "";
|
|
51943
|
+
return;
|
|
51920
51944
|
}
|
|
51945
|
+
sendPastePayloadFromDataTransfer(event.dataTransfer);
|
|
51946
|
+
imeInput.value = "";
|
|
51921
51947
|
return;
|
|
51922
51948
|
}
|
|
51923
51949
|
const text = inputHandler.encodeBeforeInput(event);
|
|
@@ -51954,13 +51980,16 @@ function createResttyApp(options) {
|
|
|
51954
51980
|
const onPaste = (event) => {
|
|
51955
51981
|
if (!wasmReady || !wasmHandle)
|
|
51956
51982
|
return;
|
|
51983
|
+
event.preventDefault();
|
|
51984
|
+
suppressNextInput = true;
|
|
51957
51985
|
const text = event.clipboardData?.getData("text/plain") || "";
|
|
51958
51986
|
if (text) {
|
|
51959
|
-
event.preventDefault();
|
|
51960
|
-
suppressNextInput = true;
|
|
51961
51987
|
sendPasteText(text);
|
|
51962
51988
|
imeInput.value = "";
|
|
51989
|
+
return;
|
|
51963
51990
|
}
|
|
51991
|
+
sendPastePayloadFromDataTransfer(event.clipboardData);
|
|
51992
|
+
imeInput.value = "";
|
|
51964
51993
|
};
|
|
51965
51994
|
imeInput.addEventListener("compositionstart", onCompositionStart);
|
|
51966
51995
|
imeInput.addEventListener("compositionupdate", onCompositionUpdate);
|
|
@@ -53235,6 +53264,36 @@ function createResttyApp(options) {
|
|
|
53235
53264
|
needsRender = true;
|
|
53236
53265
|
lastRenderTime = 0;
|
|
53237
53266
|
}
|
|
53267
|
+
function resize(cols, rows) {
|
|
53268
|
+
const nextCols = Math.max(1, Math.floor(Number(cols)));
|
|
53269
|
+
const nextRows = Math.max(1, Math.floor(Number(rows)));
|
|
53270
|
+
if (!Number.isFinite(nextCols) || !Number.isFinite(nextRows))
|
|
53271
|
+
return;
|
|
53272
|
+
const dpr = window.devicePixelRatio || 1;
|
|
53273
|
+
if (dpr !== currentDpr) {
|
|
53274
|
+
currentDpr = dpr;
|
|
53275
|
+
if (dprEl)
|
|
53276
|
+
dprEl.textContent = dpr.toFixed(2);
|
|
53277
|
+
callbacks?.onDpr?.(dpr);
|
|
53278
|
+
}
|
|
53279
|
+
const metrics = computeCellMetrics2();
|
|
53280
|
+
if (!metrics)
|
|
53281
|
+
return;
|
|
53282
|
+
canvas.width = Math.max(1, nextCols * metrics.cellW);
|
|
53283
|
+
canvas.height = Math.max(1, nextRows * metrics.cellH);
|
|
53284
|
+
if (sizeEl)
|
|
53285
|
+
sizeEl.textContent = `${canvas.width}x${canvas.height}`;
|
|
53286
|
+
callbacks?.onCanvasSize?.(canvas.width, canvas.height);
|
|
53287
|
+
resizeState.dpr = currentDpr;
|
|
53288
|
+
resizeState.active = true;
|
|
53289
|
+
resizeState.lastAt = performance.now();
|
|
53290
|
+
resizeState.cols = nextCols;
|
|
53291
|
+
resizeState.rows = nextRows;
|
|
53292
|
+
updateGrid();
|
|
53293
|
+
scheduleTerminalResizeCommit(nextCols, nextRows, { immediate: true });
|
|
53294
|
+
needsRender = true;
|
|
53295
|
+
lastRenderTime = 0;
|
|
53296
|
+
}
|
|
53238
53297
|
function scheduleSizeUpdate() {
|
|
53239
53298
|
updateSize();
|
|
53240
53299
|
if (sizeRaf)
|
|
@@ -53244,22 +53303,35 @@ function createResttyApp(options) {
|
|
|
53244
53303
|
updateSize();
|
|
53245
53304
|
});
|
|
53246
53305
|
}
|
|
53306
|
+
function focusTypingInput() {
|
|
53307
|
+
canvas.focus({ preventScroll: true });
|
|
53308
|
+
if (!imeInput)
|
|
53309
|
+
return;
|
|
53310
|
+
imeInput.focus({ preventScroll: true });
|
|
53311
|
+
if (typeof document !== "undefined" && document.activeElement !== imeInput) {
|
|
53312
|
+
requestAnimationFrame(() => {
|
|
53313
|
+
if (document.activeElement === canvas)
|
|
53314
|
+
imeInput.focus({ preventScroll: true });
|
|
53315
|
+
});
|
|
53316
|
+
}
|
|
53317
|
+
}
|
|
53318
|
+
function focus() {
|
|
53319
|
+
focusTypingInput();
|
|
53320
|
+
isFocused = typeof document !== "undefined" && imeInput ? document.activeElement === canvas || document.activeElement === imeInput : true;
|
|
53321
|
+
}
|
|
53322
|
+
function blur() {
|
|
53323
|
+
if (imeInput && document.activeElement === imeInput) {
|
|
53324
|
+
imeInput.blur();
|
|
53325
|
+
}
|
|
53326
|
+
if (document.activeElement === canvas) {
|
|
53327
|
+
canvas.blur();
|
|
53328
|
+
}
|
|
53329
|
+
isFocused = false;
|
|
53330
|
+
}
|
|
53247
53331
|
function bindFocusEvents() {
|
|
53248
53332
|
if (!attachCanvasEvents)
|
|
53249
53333
|
return;
|
|
53250
53334
|
canvas.tabIndex = 0;
|
|
53251
|
-
const focusTypingInput = () => {
|
|
53252
|
-
canvas.focus({ preventScroll: true });
|
|
53253
|
-
if (!imeInput)
|
|
53254
|
-
return;
|
|
53255
|
-
imeInput.focus({ preventScroll: true });
|
|
53256
|
-
if (typeof document !== "undefined" && document.activeElement !== imeInput) {
|
|
53257
|
-
requestAnimationFrame(() => {
|
|
53258
|
-
if (document.activeElement === canvas)
|
|
53259
|
-
imeInput.focus({ preventScroll: true });
|
|
53260
|
-
});
|
|
53261
|
-
}
|
|
53262
|
-
};
|
|
53263
53335
|
const handleFocus = () => {
|
|
53264
53336
|
isFocused = true;
|
|
53265
53337
|
focusTypingInput();
|
|
@@ -56063,12 +56135,48 @@ function createResttyApp(options) {
|
|
|
56063
56135
|
return text.replace(/\r?\n/g, `\r
|
|
56064
56136
|
`);
|
|
56065
56137
|
}
|
|
56066
|
-
function
|
|
56138
|
+
function runBeforeInputHook(text, source) {
|
|
56139
|
+
if (!beforeInputHook)
|
|
56140
|
+
return text;
|
|
56141
|
+
try {
|
|
56142
|
+
const next = beforeInputHook({ text, source });
|
|
56143
|
+
if (next === null)
|
|
56144
|
+
return null;
|
|
56145
|
+
if (typeof next === "string")
|
|
56146
|
+
return next;
|
|
56147
|
+
return text;
|
|
56148
|
+
} catch (error) {
|
|
56149
|
+
console.error("[restty] beforeInput hook error:", error);
|
|
56150
|
+
return text;
|
|
56151
|
+
}
|
|
56152
|
+
}
|
|
56153
|
+
function runBeforeRenderOutputHook(text, source) {
|
|
56154
|
+
if (!beforeRenderOutputHook)
|
|
56155
|
+
return text;
|
|
56156
|
+
try {
|
|
56157
|
+
const next = beforeRenderOutputHook({ text, source });
|
|
56158
|
+
if (next === null)
|
|
56159
|
+
return null;
|
|
56160
|
+
if (typeof next === "string")
|
|
56161
|
+
return next;
|
|
56162
|
+
return text;
|
|
56163
|
+
} catch (error) {
|
|
56164
|
+
console.error("[restty] beforeRenderOutput hook error:", error);
|
|
56165
|
+
return text;
|
|
56166
|
+
}
|
|
56167
|
+
}
|
|
56168
|
+
function sendInput(text, source = "program", options2 = {}) {
|
|
56067
56169
|
if (!wasmReady || !wasm || !wasmHandle)
|
|
56068
56170
|
return;
|
|
56069
56171
|
if (!text)
|
|
56070
56172
|
return;
|
|
56071
|
-
|
|
56173
|
+
let intercepted = text;
|
|
56174
|
+
if (!options2.skipHooks) {
|
|
56175
|
+
intercepted = source === "pty" ? runBeforeRenderOutputHook(text, source) : runBeforeInputHook(text, source);
|
|
56176
|
+
}
|
|
56177
|
+
if (!intercepted)
|
|
56178
|
+
return;
|
|
56179
|
+
const normalized = source === "pty" ? intercepted : normalizeNewlines(intercepted);
|
|
56072
56180
|
if (source === "key") {
|
|
56073
56181
|
const bytes = textEncoder3.encode(normalized);
|
|
56074
56182
|
const hex = Array.from(bytes, (b3) => b3.toString(16).padStart(2, "0")).join(" ");
|
|
@@ -56134,6 +56242,8 @@ function createResttyApp(options) {
|
|
|
56134
56242
|
return false;
|
|
56135
56243
|
}
|
|
56136
56244
|
async function pasteFromClipboard() {
|
|
56245
|
+
if (typeof navigator === "undefined" || !navigator.clipboard)
|
|
56246
|
+
return false;
|
|
56137
56247
|
try {
|
|
56138
56248
|
const text = await navigator.clipboard.readText();
|
|
56139
56249
|
if (text) {
|
|
@@ -56145,6 +56255,15 @@ function createResttyApp(options) {
|
|
|
56145
56255
|
}
|
|
56146
56256
|
return false;
|
|
56147
56257
|
}
|
|
56258
|
+
async function handlePasteShortcut(event) {
|
|
56259
|
+
const pasted = await pasteFromClipboard();
|
|
56260
|
+
if (pasted)
|
|
56261
|
+
return;
|
|
56262
|
+
const seq = inputHandler.encodeKeyEvent(event);
|
|
56263
|
+
if (!seq)
|
|
56264
|
+
return;
|
|
56265
|
+
sendKeyInput(seq);
|
|
56266
|
+
}
|
|
56148
56267
|
function clearScreen() {
|
|
56149
56268
|
sendInput("\x1B[2J\x1B[H");
|
|
56150
56269
|
}
|
|
@@ -56193,7 +56312,9 @@ function createResttyApp(options) {
|
|
|
56193
56312
|
}
|
|
56194
56313
|
if (wantsPaste) {
|
|
56195
56314
|
event.preventDefault();
|
|
56196
|
-
|
|
56315
|
+
if (imeInput)
|
|
56316
|
+
imeInput.focus({ preventScroll: true });
|
|
56317
|
+
handlePasteShortcut(event);
|
|
56197
56318
|
return;
|
|
56198
56319
|
}
|
|
56199
56320
|
const seq = inputHandler.encodeKeyEvent(event);
|
|
@@ -56395,6 +56516,9 @@ function createResttyApp(options) {
|
|
|
56395
56516
|
copySelectionToClipboard,
|
|
56396
56517
|
pasteFromClipboard,
|
|
56397
56518
|
dumpAtlasForCodepoint,
|
|
56519
|
+
resize,
|
|
56520
|
+
focus,
|
|
56521
|
+
blur,
|
|
56398
56522
|
updateSize,
|
|
56399
56523
|
getBackend: () => backend
|
|
56400
56524
|
};
|
|
@@ -56514,6 +56638,8 @@ function createResttyAppPaneManager(options) {
|
|
|
56514
56638
|
}
|
|
56515
56639
|
|
|
56516
56640
|
// src/app/restty.ts
|
|
56641
|
+
var RESTTY_PLUGIN_API_VERSION = 1;
|
|
56642
|
+
|
|
56517
56643
|
class ResttyPaneHandle {
|
|
56518
56644
|
resolvePane;
|
|
56519
56645
|
constructor(resolvePane) {
|
|
@@ -56573,6 +56699,15 @@ class ResttyPaneHandle {
|
|
|
56573
56699
|
dumpAtlasForCodepoint(cp) {
|
|
56574
56700
|
this.resolvePane().app.dumpAtlasForCodepoint(cp);
|
|
56575
56701
|
}
|
|
56702
|
+
resize(cols, rows) {
|
|
56703
|
+
this.resolvePane().app.resize(cols, rows);
|
|
56704
|
+
}
|
|
56705
|
+
focus() {
|
|
56706
|
+
this.resolvePane().app.focus();
|
|
56707
|
+
}
|
|
56708
|
+
blur() {
|
|
56709
|
+
this.resolvePane().app.blur();
|
|
56710
|
+
}
|
|
56576
56711
|
updateSize(force) {
|
|
56577
56712
|
this.resolvePane().app.updateSize(force);
|
|
56578
56713
|
}
|
|
@@ -56587,25 +56722,105 @@ class ResttyPaneHandle {
|
|
|
56587
56722
|
class Restty {
|
|
56588
56723
|
paneManager;
|
|
56589
56724
|
fontSources;
|
|
56725
|
+
pluginListeners = new Map;
|
|
56726
|
+
pluginRuntimes = new Map;
|
|
56727
|
+
pluginDiagnostics = new Map;
|
|
56728
|
+
inputInterceptors = [];
|
|
56729
|
+
outputInterceptors = [];
|
|
56730
|
+
lifecycleHooks = [];
|
|
56731
|
+
renderHooks = [];
|
|
56732
|
+
nextInterceptorId = 1;
|
|
56733
|
+
nextInterceptorOrder = 1;
|
|
56590
56734
|
constructor(options) {
|
|
56591
|
-
const {
|
|
56735
|
+
const {
|
|
56736
|
+
createInitialPane = true,
|
|
56737
|
+
appOptions,
|
|
56738
|
+
fontSources,
|
|
56739
|
+
onPaneCreated,
|
|
56740
|
+
onPaneClosed,
|
|
56741
|
+
onPaneSplit,
|
|
56742
|
+
onActivePaneChange,
|
|
56743
|
+
onLayoutChanged,
|
|
56744
|
+
...paneManagerOptions
|
|
56745
|
+
} = options;
|
|
56592
56746
|
this.fontSources = fontSources ? [...fontSources] : undefined;
|
|
56593
56747
|
const mergedAppOptions = (context) => {
|
|
56594
56748
|
const resolved = typeof appOptions === "function" ? appOptions(context) : appOptions ?? {};
|
|
56595
|
-
|
|
56596
|
-
|
|
56749
|
+
const resolvedBeforeInput = resolved.beforeInput;
|
|
56750
|
+
const resolvedBeforeRenderOutput = resolved.beforeRenderOutput;
|
|
56597
56751
|
return {
|
|
56598
56752
|
...resolved,
|
|
56599
|
-
fontSources: this.fontSources
|
|
56753
|
+
...this.fontSources ? { fontSources: this.fontSources } : {},
|
|
56754
|
+
beforeInput: ({ text, source }) => {
|
|
56755
|
+
const maybeUserText = resolvedBeforeInput?.({ text, source });
|
|
56756
|
+
if (maybeUserText === null)
|
|
56757
|
+
return null;
|
|
56758
|
+
const current = maybeUserText === undefined ? text : maybeUserText;
|
|
56759
|
+
return this.applyInputInterceptors(context.id, current, source);
|
|
56760
|
+
},
|
|
56761
|
+
beforeRenderOutput: ({ text, source }) => {
|
|
56762
|
+
this.runRenderHooks({
|
|
56763
|
+
phase: "before",
|
|
56764
|
+
paneId: context.id,
|
|
56765
|
+
text,
|
|
56766
|
+
source,
|
|
56767
|
+
dropped: false
|
|
56768
|
+
});
|
|
56769
|
+
const maybeUserText = resolvedBeforeRenderOutput?.({ text, source });
|
|
56770
|
+
if (maybeUserText === null) {
|
|
56771
|
+
this.runRenderHooks({
|
|
56772
|
+
phase: "after",
|
|
56773
|
+
paneId: context.id,
|
|
56774
|
+
text,
|
|
56775
|
+
source,
|
|
56776
|
+
dropped: true
|
|
56777
|
+
});
|
|
56778
|
+
return null;
|
|
56779
|
+
}
|
|
56780
|
+
const current = maybeUserText === undefined ? text : maybeUserText;
|
|
56781
|
+
const next = this.applyOutputInterceptors(context.id, current, source);
|
|
56782
|
+
this.runRenderHooks({
|
|
56783
|
+
phase: "after",
|
|
56784
|
+
paneId: context.id,
|
|
56785
|
+
text: next === null ? current : next,
|
|
56786
|
+
source,
|
|
56787
|
+
dropped: next === null
|
|
56788
|
+
});
|
|
56789
|
+
return next;
|
|
56790
|
+
}
|
|
56600
56791
|
};
|
|
56601
56792
|
};
|
|
56602
56793
|
this.paneManager = createResttyAppPaneManager({
|
|
56603
56794
|
...paneManagerOptions,
|
|
56604
|
-
appOptions: mergedAppOptions
|
|
56795
|
+
appOptions: mergedAppOptions,
|
|
56796
|
+
onPaneCreated: (pane) => {
|
|
56797
|
+
this.emitPluginEvent("pane:created", { paneId: pane.id });
|
|
56798
|
+
onPaneCreated?.(pane);
|
|
56799
|
+
},
|
|
56800
|
+
onPaneClosed: (pane) => {
|
|
56801
|
+
this.emitPluginEvent("pane:closed", { paneId: pane.id });
|
|
56802
|
+
onPaneClosed?.(pane);
|
|
56803
|
+
},
|
|
56804
|
+
onPaneSplit: (sourcePane, createdPane, direction) => {
|
|
56805
|
+
this.emitPluginEvent("pane:split", {
|
|
56806
|
+
sourcePaneId: sourcePane.id,
|
|
56807
|
+
createdPaneId: createdPane.id,
|
|
56808
|
+
direction
|
|
56809
|
+
});
|
|
56810
|
+
onPaneSplit?.(sourcePane, createdPane, direction);
|
|
56811
|
+
},
|
|
56812
|
+
onActivePaneChange: (pane) => {
|
|
56813
|
+
this.emitPluginEvent("pane:active-changed", { paneId: pane?.id ?? null });
|
|
56814
|
+
onActivePaneChange?.(pane);
|
|
56815
|
+
},
|
|
56816
|
+
onLayoutChanged: () => {
|
|
56817
|
+
this.emitPluginEvent("layout:changed", {});
|
|
56818
|
+
onLayoutChanged?.();
|
|
56819
|
+
}
|
|
56605
56820
|
});
|
|
56606
56821
|
if (createInitialPane) {
|
|
56607
56822
|
const focus = typeof createInitialPane === "object" ? createInitialPane.focus ?? true : true;
|
|
56608
|
-
this.
|
|
56823
|
+
this.createInitialPane({ focus });
|
|
56609
56824
|
}
|
|
56610
56825
|
}
|
|
56611
56826
|
getPanes() {
|
|
@@ -56656,16 +56871,63 @@ class Restty {
|
|
|
56656
56871
|
await Promise.all(updates);
|
|
56657
56872
|
}
|
|
56658
56873
|
createInitialPane(options) {
|
|
56659
|
-
|
|
56874
|
+
this.runLifecycleHooks({ phase: "before", action: "create-initial-pane" });
|
|
56875
|
+
const pane = this.paneManager.createInitialPane(options);
|
|
56876
|
+
this.runLifecycleHooks({
|
|
56877
|
+
phase: "after",
|
|
56878
|
+
action: "create-initial-pane",
|
|
56879
|
+
paneId: pane.id,
|
|
56880
|
+
ok: true
|
|
56881
|
+
});
|
|
56882
|
+
return pane;
|
|
56660
56883
|
}
|
|
56661
56884
|
splitActivePane(direction) {
|
|
56662
|
-
|
|
56885
|
+
const sourcePaneId = this.getActivePane()?.id ?? null;
|
|
56886
|
+
this.runLifecycleHooks({
|
|
56887
|
+
phase: "before",
|
|
56888
|
+
action: "split-active-pane",
|
|
56889
|
+
paneId: sourcePaneId,
|
|
56890
|
+
direction
|
|
56891
|
+
});
|
|
56892
|
+
const pane = this.paneManager.splitActivePane(direction);
|
|
56893
|
+
this.runLifecycleHooks({
|
|
56894
|
+
phase: "after",
|
|
56895
|
+
action: "split-active-pane",
|
|
56896
|
+
sourcePaneId: sourcePaneId ?? undefined,
|
|
56897
|
+
createdPaneId: pane?.id ?? null,
|
|
56898
|
+
direction,
|
|
56899
|
+
ok: !!pane
|
|
56900
|
+
});
|
|
56901
|
+
return pane;
|
|
56663
56902
|
}
|
|
56664
56903
|
splitPane(id, direction) {
|
|
56665
|
-
|
|
56904
|
+
this.runLifecycleHooks({
|
|
56905
|
+
phase: "before",
|
|
56906
|
+
action: "split-pane",
|
|
56907
|
+
paneId: id,
|
|
56908
|
+
direction
|
|
56909
|
+
});
|
|
56910
|
+
const pane = this.paneManager.splitPane(id, direction);
|
|
56911
|
+
this.runLifecycleHooks({
|
|
56912
|
+
phase: "after",
|
|
56913
|
+
action: "split-pane",
|
|
56914
|
+
sourcePaneId: id,
|
|
56915
|
+
createdPaneId: pane?.id ?? null,
|
|
56916
|
+
direction,
|
|
56917
|
+
ok: !!pane
|
|
56918
|
+
});
|
|
56919
|
+
return pane;
|
|
56666
56920
|
}
|
|
56667
56921
|
closePane(id) {
|
|
56668
|
-
|
|
56922
|
+
this.runLifecycleHooks({ phase: "before", action: "close-pane", paneId: id });
|
|
56923
|
+
const ok = this.paneManager.closePane(id);
|
|
56924
|
+
this.runLifecycleHooks({
|
|
56925
|
+
phase: "after",
|
|
56926
|
+
action: "close-pane",
|
|
56927
|
+
paneId: id,
|
|
56928
|
+
ok
|
|
56929
|
+
});
|
|
56930
|
+
return ok;
|
|
56669
56931
|
}
|
|
56670
56932
|
getPaneStyleOptions() {
|
|
56671
56933
|
return this.paneManager.getStyleOptions();
|
|
@@ -56674,10 +56936,34 @@ class Restty {
|
|
|
56674
56936
|
this.paneManager.setStyleOptions(options);
|
|
56675
56937
|
}
|
|
56676
56938
|
setActivePane(id, options) {
|
|
56939
|
+
this.runLifecycleHooks({
|
|
56940
|
+
phase: "before",
|
|
56941
|
+
action: "set-active-pane",
|
|
56942
|
+
paneId: id
|
|
56943
|
+
});
|
|
56677
56944
|
this.paneManager.setActivePane(id, options);
|
|
56945
|
+
const activePaneId = this.getActivePane()?.id ?? null;
|
|
56946
|
+
this.runLifecycleHooks({
|
|
56947
|
+
phase: "after",
|
|
56948
|
+
action: "set-active-pane",
|
|
56949
|
+
paneId: activePaneId,
|
|
56950
|
+
ok: activePaneId === id
|
|
56951
|
+
});
|
|
56678
56952
|
}
|
|
56679
56953
|
markPaneFocused(id, options) {
|
|
56954
|
+
this.runLifecycleHooks({
|
|
56955
|
+
phase: "before",
|
|
56956
|
+
action: "mark-pane-focused",
|
|
56957
|
+
paneId: id
|
|
56958
|
+
});
|
|
56680
56959
|
this.paneManager.markPaneFocused(id, options);
|
|
56960
|
+
const focusedPaneId = this.getFocusedPane()?.id ?? null;
|
|
56961
|
+
this.runLifecycleHooks({
|
|
56962
|
+
phase: "after",
|
|
56963
|
+
action: "mark-pane-focused",
|
|
56964
|
+
paneId: focusedPaneId,
|
|
56965
|
+
ok: focusedPaneId === id
|
|
56966
|
+
});
|
|
56681
56967
|
}
|
|
56682
56968
|
requestLayoutSync() {
|
|
56683
56969
|
this.paneManager.requestLayoutSync();
|
|
@@ -56685,14 +56971,193 @@ class Restty {
|
|
|
56685
56971
|
hideContextMenu() {
|
|
56686
56972
|
this.paneManager.hideContextMenu();
|
|
56687
56973
|
}
|
|
56974
|
+
async use(plugin, options) {
|
|
56975
|
+
if (!plugin || typeof plugin !== "object") {
|
|
56976
|
+
throw new Error("Restty plugin must be an object");
|
|
56977
|
+
}
|
|
56978
|
+
const pluginId = plugin.id?.trim?.() ?? "";
|
|
56979
|
+
if (!pluginId) {
|
|
56980
|
+
throw new Error("Restty plugin id is required");
|
|
56981
|
+
}
|
|
56982
|
+
if (typeof plugin.activate !== "function") {
|
|
56983
|
+
throw new Error(`Restty plugin ${pluginId} must define activate(context)`);
|
|
56984
|
+
}
|
|
56985
|
+
if (this.pluginRuntimes.has(pluginId))
|
|
56986
|
+
return;
|
|
56987
|
+
try {
|
|
56988
|
+
this.assertPluginCompatibility(pluginId, plugin);
|
|
56989
|
+
} catch (error) {
|
|
56990
|
+
this.pluginDiagnostics.set(pluginId, {
|
|
56991
|
+
id: pluginId,
|
|
56992
|
+
version: plugin.version?.trim?.() || null,
|
|
56993
|
+
apiVersion: Number.isFinite(plugin.apiVersion) ? Number(plugin.apiVersion) : null,
|
|
56994
|
+
requires: plugin.requires ?? null,
|
|
56995
|
+
active: false,
|
|
56996
|
+
activatedAt: null,
|
|
56997
|
+
lastError: this.errorToMessage(error)
|
|
56998
|
+
});
|
|
56999
|
+
throw error;
|
|
57000
|
+
}
|
|
57001
|
+
const runtime2 = {
|
|
57002
|
+
plugin: this.normalizePluginMetadata(plugin, pluginId),
|
|
57003
|
+
cleanup: null,
|
|
57004
|
+
activatedAt: Date.now(),
|
|
57005
|
+
options,
|
|
57006
|
+
disposers: []
|
|
57007
|
+
};
|
|
57008
|
+
this.pluginDiagnostics.set(pluginId, {
|
|
57009
|
+
id: pluginId,
|
|
57010
|
+
version: runtime2.plugin.version?.trim?.() || null,
|
|
57011
|
+
apiVersion: Number.isFinite(runtime2.plugin.apiVersion) ? Number(runtime2.plugin.apiVersion) : null,
|
|
57012
|
+
requires: runtime2.plugin.requires ?? null,
|
|
57013
|
+
active: false,
|
|
57014
|
+
activatedAt: null,
|
|
57015
|
+
lastError: null
|
|
57016
|
+
});
|
|
57017
|
+
this.pluginRuntimes.set(pluginId, runtime2);
|
|
57018
|
+
try {
|
|
57019
|
+
const cleanup = await runtime2.plugin.activate(this.createPluginContext(runtime2), runtime2.options);
|
|
57020
|
+
runtime2.cleanup = this.normalizePluginCleanup(cleanup);
|
|
57021
|
+
runtime2.activatedAt = Date.now();
|
|
57022
|
+
this.updatePluginDiagnostic(pluginId, {
|
|
57023
|
+
active: true,
|
|
57024
|
+
activatedAt: runtime2.activatedAt,
|
|
57025
|
+
lastError: null
|
|
57026
|
+
});
|
|
57027
|
+
this.emitPluginEvent("plugin:activated", { pluginId });
|
|
57028
|
+
} catch (error) {
|
|
57029
|
+
this.teardownPluginRuntime(runtime2);
|
|
57030
|
+
this.pluginRuntimes.delete(pluginId);
|
|
57031
|
+
this.updatePluginDiagnostic(pluginId, {
|
|
57032
|
+
active: false,
|
|
57033
|
+
activatedAt: null,
|
|
57034
|
+
lastError: this.errorToMessage(error)
|
|
57035
|
+
});
|
|
57036
|
+
throw error;
|
|
57037
|
+
}
|
|
57038
|
+
}
|
|
57039
|
+
async loadPlugins(manifest, registry) {
|
|
57040
|
+
const results = [];
|
|
57041
|
+
for (let i3 = 0;i3 < manifest.length; i3 += 1) {
|
|
57042
|
+
const item = manifest[i3];
|
|
57043
|
+
const pluginId = item.id?.trim?.() ?? "";
|
|
57044
|
+
if (!pluginId) {
|
|
57045
|
+
results.push({
|
|
57046
|
+
id: "",
|
|
57047
|
+
status: "failed",
|
|
57048
|
+
error: "Restty plugin manifest entry is missing id"
|
|
57049
|
+
});
|
|
57050
|
+
continue;
|
|
57051
|
+
}
|
|
57052
|
+
if (item.enabled === false) {
|
|
57053
|
+
results.push({ id: pluginId, status: "skipped", error: null });
|
|
57054
|
+
continue;
|
|
57055
|
+
}
|
|
57056
|
+
const entry = this.lookupPluginRegistryEntry(registry, pluginId);
|
|
57057
|
+
if (!entry) {
|
|
57058
|
+
const message = `Restty plugin ${pluginId} was not found in registry`;
|
|
57059
|
+
this.setPluginLoadError(pluginId, message);
|
|
57060
|
+
results.push({ id: pluginId, status: "missing", error: message });
|
|
57061
|
+
continue;
|
|
57062
|
+
}
|
|
57063
|
+
let plugin;
|
|
57064
|
+
try {
|
|
57065
|
+
plugin = await this.resolvePluginRegistryEntry(entry);
|
|
57066
|
+
} catch (error) {
|
|
57067
|
+
const message = this.errorToMessage(error);
|
|
57068
|
+
this.setPluginLoadError(pluginId, message);
|
|
57069
|
+
results.push({ id: pluginId, status: "failed", error: message });
|
|
57070
|
+
continue;
|
|
57071
|
+
}
|
|
57072
|
+
const resolvedId = plugin.id?.trim?.() ?? "";
|
|
57073
|
+
if (resolvedId !== pluginId) {
|
|
57074
|
+
const message = `Restty plugin registry entry ${pluginId} resolved to id ${resolvedId || "(empty)"}`;
|
|
57075
|
+
this.setPluginLoadError(pluginId, message);
|
|
57076
|
+
results.push({ id: pluginId, status: "failed", error: message });
|
|
57077
|
+
continue;
|
|
57078
|
+
}
|
|
57079
|
+
try {
|
|
57080
|
+
await this.use(plugin, item.options);
|
|
57081
|
+
results.push({ id: pluginId, status: "loaded", error: null });
|
|
57082
|
+
} catch (error) {
|
|
57083
|
+
results.push({
|
|
57084
|
+
id: pluginId,
|
|
57085
|
+
status: "failed",
|
|
57086
|
+
error: this.errorToMessage(error)
|
|
57087
|
+
});
|
|
57088
|
+
}
|
|
57089
|
+
}
|
|
57090
|
+
return results;
|
|
57091
|
+
}
|
|
57092
|
+
unuse(pluginId) {
|
|
57093
|
+
const key = pluginId?.trim?.() ?? "";
|
|
57094
|
+
if (!key)
|
|
57095
|
+
return false;
|
|
57096
|
+
const runtime2 = this.pluginRuntimes.get(key);
|
|
57097
|
+
if (!runtime2)
|
|
57098
|
+
return false;
|
|
57099
|
+
this.pluginRuntimes.delete(key);
|
|
57100
|
+
this.teardownPluginRuntime(runtime2);
|
|
57101
|
+
this.updatePluginDiagnostic(key, {
|
|
57102
|
+
active: false,
|
|
57103
|
+
activatedAt: null
|
|
57104
|
+
});
|
|
57105
|
+
this.emitPluginEvent("plugin:deactivated", { pluginId: key });
|
|
57106
|
+
return true;
|
|
57107
|
+
}
|
|
57108
|
+
plugins() {
|
|
57109
|
+
return Array.from(this.pluginRuntimes.keys());
|
|
57110
|
+
}
|
|
57111
|
+
pluginInfo(pluginId) {
|
|
57112
|
+
if (typeof pluginId === "string") {
|
|
57113
|
+
const key = pluginId.trim();
|
|
57114
|
+
if (!key)
|
|
57115
|
+
return null;
|
|
57116
|
+
return this.buildPluginInfo(key);
|
|
57117
|
+
}
|
|
57118
|
+
const keys = new Set;
|
|
57119
|
+
for (const key of this.pluginDiagnostics.keys())
|
|
57120
|
+
keys.add(key);
|
|
57121
|
+
for (const key of this.pluginRuntimes.keys())
|
|
57122
|
+
keys.add(key);
|
|
57123
|
+
return Array.from(keys).sort((a3, b3) => a3.localeCompare(b3)).map((key) => this.buildPluginInfo(key)).filter((entry) => entry !== null);
|
|
57124
|
+
}
|
|
56688
57125
|
destroy() {
|
|
57126
|
+
const pluginIds = this.plugins();
|
|
57127
|
+
for (let i3 = 0;i3 < pluginIds.length; i3 += 1) {
|
|
57128
|
+
this.unuse(pluginIds[i3]);
|
|
57129
|
+
}
|
|
56689
57130
|
this.paneManager.destroy();
|
|
56690
57131
|
}
|
|
56691
57132
|
connectPty(url = "") {
|
|
56692
|
-
this.requireActivePaneHandle()
|
|
57133
|
+
const pane = this.requireActivePaneHandle();
|
|
57134
|
+
this.runLifecycleHooks({
|
|
57135
|
+
phase: "before",
|
|
57136
|
+
action: "connect-pty",
|
|
57137
|
+
paneId: pane.id
|
|
57138
|
+
});
|
|
57139
|
+
pane.connectPty(url);
|
|
57140
|
+
this.runLifecycleHooks({
|
|
57141
|
+
phase: "after",
|
|
57142
|
+
action: "connect-pty",
|
|
57143
|
+
paneId: pane.id,
|
|
57144
|
+
ok: true
|
|
57145
|
+
});
|
|
56693
57146
|
}
|
|
56694
57147
|
disconnectPty() {
|
|
56695
|
-
this.requireActivePaneHandle()
|
|
57148
|
+
const pane = this.requireActivePaneHandle();
|
|
57149
|
+
this.runLifecycleHooks({
|
|
57150
|
+
phase: "before",
|
|
57151
|
+
action: "disconnect-pty",
|
|
57152
|
+
paneId: pane.id
|
|
57153
|
+
});
|
|
57154
|
+
pane.disconnectPty();
|
|
57155
|
+
this.runLifecycleHooks({
|
|
57156
|
+
phase: "after",
|
|
57157
|
+
action: "disconnect-pty",
|
|
57158
|
+
paneId: pane.id,
|
|
57159
|
+
ok: true
|
|
57160
|
+
});
|
|
56696
57161
|
}
|
|
56697
57162
|
isPtyConnected() {
|
|
56698
57163
|
return this.requireActivePaneHandle().isPtyConnected();
|
|
@@ -56739,6 +57204,58 @@ class Restty {
|
|
|
56739
57204
|
dumpAtlasForCodepoint(cp) {
|
|
56740
57205
|
this.requireActivePaneHandle().dumpAtlasForCodepoint(cp);
|
|
56741
57206
|
}
|
|
57207
|
+
resize(cols, rows) {
|
|
57208
|
+
const pane = this.requireActivePaneHandle();
|
|
57209
|
+
this.runLifecycleHooks({
|
|
57210
|
+
phase: "before",
|
|
57211
|
+
action: "resize",
|
|
57212
|
+
paneId: pane.id,
|
|
57213
|
+
cols,
|
|
57214
|
+
rows
|
|
57215
|
+
});
|
|
57216
|
+
pane.resize(cols, rows);
|
|
57217
|
+
this.runLifecycleHooks({
|
|
57218
|
+
phase: "after",
|
|
57219
|
+
action: "resize",
|
|
57220
|
+
paneId: pane.id,
|
|
57221
|
+
cols,
|
|
57222
|
+
rows,
|
|
57223
|
+
ok: true
|
|
57224
|
+
});
|
|
57225
|
+
this.emitPluginEvent("pane:resized", { paneId: pane.id, cols, rows });
|
|
57226
|
+
}
|
|
57227
|
+
focus() {
|
|
57228
|
+
const pane = this.requireActivePaneHandle();
|
|
57229
|
+
this.runLifecycleHooks({
|
|
57230
|
+
phase: "before",
|
|
57231
|
+
action: "focus",
|
|
57232
|
+
paneId: pane.id
|
|
57233
|
+
});
|
|
57234
|
+
pane.focus();
|
|
57235
|
+
this.runLifecycleHooks({
|
|
57236
|
+
phase: "after",
|
|
57237
|
+
action: "focus",
|
|
57238
|
+
paneId: pane.id,
|
|
57239
|
+
ok: true
|
|
57240
|
+
});
|
|
57241
|
+
this.emitPluginEvent("pane:focused", { paneId: pane.id });
|
|
57242
|
+
}
|
|
57243
|
+
blur() {
|
|
57244
|
+
const pane = this.requireActivePaneHandle();
|
|
57245
|
+
this.runLifecycleHooks({
|
|
57246
|
+
phase: "before",
|
|
57247
|
+
action: "blur",
|
|
57248
|
+
paneId: pane.id
|
|
57249
|
+
});
|
|
57250
|
+
pane.blur();
|
|
57251
|
+
this.runLifecycleHooks({
|
|
57252
|
+
phase: "after",
|
|
57253
|
+
action: "blur",
|
|
57254
|
+
paneId: pane.id,
|
|
57255
|
+
ok: true
|
|
57256
|
+
});
|
|
57257
|
+
this.emitPluginEvent("pane:blurred", { paneId: pane.id });
|
|
57258
|
+
}
|
|
56742
57259
|
updateSize(force) {
|
|
56743
57260
|
this.requireActivePaneHandle().updateSize(force);
|
|
56744
57261
|
}
|
|
@@ -56761,9 +57278,300 @@ class Restty {
|
|
|
56761
57278
|
}
|
|
56762
57279
|
return this.makePaneHandle(pane.id);
|
|
56763
57280
|
}
|
|
57281
|
+
createPluginContext(runtime2) {
|
|
57282
|
+
return {
|
|
57283
|
+
restty: this,
|
|
57284
|
+
options: runtime2.options,
|
|
57285
|
+
panes: () => this.panes(),
|
|
57286
|
+
pane: (id) => this.pane(id),
|
|
57287
|
+
activePane: () => this.activePane(),
|
|
57288
|
+
focusedPane: () => this.focusedPane(),
|
|
57289
|
+
on: (event, listener) => {
|
|
57290
|
+
return {
|
|
57291
|
+
dispose: this.attachRuntimeDisposer(runtime2, "event", this.onPluginEvent(event, listener))
|
|
57292
|
+
};
|
|
57293
|
+
},
|
|
57294
|
+
addInputInterceptor: (interceptor, options) => {
|
|
57295
|
+
return {
|
|
57296
|
+
dispose: this.attachRuntimeDisposer(runtime2, "input-interceptor", this.addInputInterceptor(runtime2.plugin.id, interceptor, options))
|
|
57297
|
+
};
|
|
57298
|
+
},
|
|
57299
|
+
addOutputInterceptor: (interceptor, options) => {
|
|
57300
|
+
return {
|
|
57301
|
+
dispose: this.attachRuntimeDisposer(runtime2, "output-interceptor", this.addOutputInterceptor(runtime2.plugin.id, interceptor, options))
|
|
57302
|
+
};
|
|
57303
|
+
},
|
|
57304
|
+
addLifecycleHook: (hook, options) => {
|
|
57305
|
+
return {
|
|
57306
|
+
dispose: this.attachRuntimeDisposer(runtime2, "lifecycle-hook", this.addLifecycleHook(runtime2.plugin.id, hook, options))
|
|
57307
|
+
};
|
|
57308
|
+
},
|
|
57309
|
+
addRenderHook: (hook, options) => {
|
|
57310
|
+
return {
|
|
57311
|
+
dispose: this.attachRuntimeDisposer(runtime2, "render-hook", this.addRenderHook(runtime2.plugin.id, hook, options))
|
|
57312
|
+
};
|
|
57313
|
+
}
|
|
57314
|
+
};
|
|
57315
|
+
}
|
|
57316
|
+
attachRuntimeDisposer(runtime2, kind, dispose) {
|
|
57317
|
+
const entry = {
|
|
57318
|
+
kind,
|
|
57319
|
+
active: true,
|
|
57320
|
+
dispose: () => {
|
|
57321
|
+
if (!entry.active)
|
|
57322
|
+
return;
|
|
57323
|
+
entry.active = false;
|
|
57324
|
+
dispose();
|
|
57325
|
+
}
|
|
57326
|
+
};
|
|
57327
|
+
runtime2.disposers.push(entry);
|
|
57328
|
+
return entry.dispose;
|
|
57329
|
+
}
|
|
57330
|
+
addInputInterceptor(pluginId, interceptor, options) {
|
|
57331
|
+
return this.registerInterceptor(this.inputInterceptors, pluginId, interceptor, options);
|
|
57332
|
+
}
|
|
57333
|
+
addOutputInterceptor(pluginId, interceptor, options) {
|
|
57334
|
+
return this.registerInterceptor(this.outputInterceptors, pluginId, interceptor, options);
|
|
57335
|
+
}
|
|
57336
|
+
addLifecycleHook(pluginId, hook, options) {
|
|
57337
|
+
return this.registerInterceptor(this.lifecycleHooks, pluginId, hook, options);
|
|
57338
|
+
}
|
|
57339
|
+
addRenderHook(pluginId, hook, options) {
|
|
57340
|
+
return this.registerInterceptor(this.renderHooks, pluginId, hook, options);
|
|
57341
|
+
}
|
|
57342
|
+
registerInterceptor(bucket, pluginId, interceptor, options) {
|
|
57343
|
+
const entry = {
|
|
57344
|
+
id: this.nextInterceptorId++,
|
|
57345
|
+
pluginId,
|
|
57346
|
+
priority: Number.isFinite(options?.priority) ? Number(options?.priority) : 0,
|
|
57347
|
+
order: this.nextInterceptorOrder++,
|
|
57348
|
+
interceptor
|
|
57349
|
+
};
|
|
57350
|
+
bucket.push(entry);
|
|
57351
|
+
bucket.sort((a3, b3) => {
|
|
57352
|
+
if (a3.priority !== b3.priority)
|
|
57353
|
+
return a3.priority - b3.priority;
|
|
57354
|
+
return a3.order - b3.order;
|
|
57355
|
+
});
|
|
57356
|
+
return () => {
|
|
57357
|
+
const index = bucket.findIndex((current) => current.id === entry.id);
|
|
57358
|
+
if (index >= 0) {
|
|
57359
|
+
bucket.splice(index, 1);
|
|
57360
|
+
}
|
|
57361
|
+
};
|
|
57362
|
+
}
|
|
57363
|
+
applyInputInterceptors(paneId, text, source) {
|
|
57364
|
+
return this.applyInterceptors(this.inputInterceptors, "input", { paneId, text, source });
|
|
57365
|
+
}
|
|
57366
|
+
applyOutputInterceptors(paneId, text, source) {
|
|
57367
|
+
return this.applyInterceptors(this.outputInterceptors, "output", { paneId, text, source });
|
|
57368
|
+
}
|
|
57369
|
+
runLifecycleHooks(payload) {
|
|
57370
|
+
this.runHooks(this.lifecycleHooks, "lifecycle", payload);
|
|
57371
|
+
}
|
|
57372
|
+
runRenderHooks(payload) {
|
|
57373
|
+
this.runHooks(this.renderHooks, "render", payload);
|
|
57374
|
+
}
|
|
57375
|
+
applyInterceptors(bucket, kind, payload) {
|
|
57376
|
+
let currentText = payload.text;
|
|
57377
|
+
for (let i3 = 0;i3 < bucket.length; i3 += 1) {
|
|
57378
|
+
const entry = bucket[i3];
|
|
57379
|
+
try {
|
|
57380
|
+
const result = entry.interceptor({ ...payload, text: currentText });
|
|
57381
|
+
if (result === null)
|
|
57382
|
+
return null;
|
|
57383
|
+
if (typeof result === "string")
|
|
57384
|
+
currentText = result;
|
|
57385
|
+
} catch (error) {
|
|
57386
|
+
console.error(`[restty plugin] ${kind} interceptor error (${entry.pluginId}):`, error);
|
|
57387
|
+
}
|
|
57388
|
+
}
|
|
57389
|
+
return currentText;
|
|
57390
|
+
}
|
|
57391
|
+
runHooks(bucket, kind, payload) {
|
|
57392
|
+
for (let i3 = 0;i3 < bucket.length; i3 += 1) {
|
|
57393
|
+
const entry = bucket[i3];
|
|
57394
|
+
try {
|
|
57395
|
+
entry.interceptor(payload);
|
|
57396
|
+
} catch (error) {
|
|
57397
|
+
console.error(`[restty plugin] ${kind} hook error (${entry.pluginId}):`, error);
|
|
57398
|
+
}
|
|
57399
|
+
}
|
|
57400
|
+
}
|
|
57401
|
+
normalizePluginMetadata(plugin, pluginId) {
|
|
57402
|
+
return {
|
|
57403
|
+
...plugin,
|
|
57404
|
+
id: pluginId,
|
|
57405
|
+
version: plugin.version?.trim?.() || undefined,
|
|
57406
|
+
apiVersion: Number.isFinite(plugin.apiVersion) ? Math.trunc(Number(plugin.apiVersion)) : undefined,
|
|
57407
|
+
requires: plugin.requires ?? undefined
|
|
57408
|
+
};
|
|
57409
|
+
}
|
|
57410
|
+
assertPluginCompatibility(pluginId, plugin) {
|
|
57411
|
+
const version = plugin.version?.trim?.();
|
|
57412
|
+
if (version !== undefined && !version) {
|
|
57413
|
+
throw new Error(`Restty plugin ${pluginId} has an empty version`);
|
|
57414
|
+
}
|
|
57415
|
+
if (plugin.apiVersion !== undefined) {
|
|
57416
|
+
if (!Number.isInteger(plugin.apiVersion) || plugin.apiVersion < 1) {
|
|
57417
|
+
throw new Error(`Restty plugin ${pluginId} has invalid apiVersion ${String(plugin.apiVersion)}`);
|
|
57418
|
+
}
|
|
57419
|
+
if (plugin.apiVersion !== RESTTY_PLUGIN_API_VERSION) {
|
|
57420
|
+
throw new Error(`Restty plugin ${pluginId} requires apiVersion ${plugin.apiVersion}, current is ${RESTTY_PLUGIN_API_VERSION}`);
|
|
57421
|
+
}
|
|
57422
|
+
}
|
|
57423
|
+
const requirement = plugin.requires?.pluginApi;
|
|
57424
|
+
if (requirement === undefined)
|
|
57425
|
+
return;
|
|
57426
|
+
if (typeof requirement === "number") {
|
|
57427
|
+
if (!Number.isInteger(requirement) || requirement < 1) {
|
|
57428
|
+
throw new Error(`Restty plugin ${pluginId} has invalid requires.pluginApi value`);
|
|
57429
|
+
}
|
|
57430
|
+
if (requirement !== RESTTY_PLUGIN_API_VERSION) {
|
|
57431
|
+
throw new Error(`Restty plugin ${pluginId} requires pluginApi ${requirement}, current is ${RESTTY_PLUGIN_API_VERSION}`);
|
|
57432
|
+
}
|
|
57433
|
+
return;
|
|
57434
|
+
}
|
|
57435
|
+
const min = requirement.min;
|
|
57436
|
+
const max = requirement.max;
|
|
57437
|
+
if (!Number.isInteger(min) || min < 1) {
|
|
57438
|
+
throw new Error(`Restty plugin ${pluginId} has invalid requires.pluginApi.min`);
|
|
57439
|
+
}
|
|
57440
|
+
if (max !== undefined && (!Number.isInteger(max) || max < min)) {
|
|
57441
|
+
throw new Error(`Restty plugin ${pluginId} has invalid requires.pluginApi.max`);
|
|
57442
|
+
}
|
|
57443
|
+
if (RESTTY_PLUGIN_API_VERSION < min || max !== undefined && RESTTY_PLUGIN_API_VERSION > max) {
|
|
57444
|
+
const range = max === undefined ? `>=${min}` : `${min}-${max}`;
|
|
57445
|
+
throw new Error(`Restty plugin ${pluginId} requires pluginApi range ${range}, current is ${RESTTY_PLUGIN_API_VERSION}`);
|
|
57446
|
+
}
|
|
57447
|
+
}
|
|
57448
|
+
lookupPluginRegistryEntry(registry, pluginId) {
|
|
57449
|
+
if (registry instanceof Map) {
|
|
57450
|
+
return registry.get(pluginId) ?? null;
|
|
57451
|
+
}
|
|
57452
|
+
if (Object.prototype.hasOwnProperty.call(registry, pluginId)) {
|
|
57453
|
+
return registry[pluginId];
|
|
57454
|
+
}
|
|
57455
|
+
return null;
|
|
57456
|
+
}
|
|
57457
|
+
async resolvePluginRegistryEntry(entry) {
|
|
57458
|
+
if (typeof entry === "function") {
|
|
57459
|
+
return await entry();
|
|
57460
|
+
}
|
|
57461
|
+
return entry;
|
|
57462
|
+
}
|
|
57463
|
+
setPluginLoadError(pluginId, message) {
|
|
57464
|
+
this.pluginDiagnostics.set(pluginId, {
|
|
57465
|
+
id: pluginId,
|
|
57466
|
+
version: null,
|
|
57467
|
+
apiVersion: null,
|
|
57468
|
+
requires: null,
|
|
57469
|
+
active: false,
|
|
57470
|
+
activatedAt: null,
|
|
57471
|
+
lastError: message
|
|
57472
|
+
});
|
|
57473
|
+
}
|
|
57474
|
+
updatePluginDiagnostic(pluginId, patch) {
|
|
57475
|
+
const current = this.pluginDiagnostics.get(pluginId);
|
|
57476
|
+
if (!current)
|
|
57477
|
+
return;
|
|
57478
|
+
this.pluginDiagnostics.set(pluginId, {
|
|
57479
|
+
...current,
|
|
57480
|
+
...patch
|
|
57481
|
+
});
|
|
57482
|
+
}
|
|
57483
|
+
buildPluginInfo(pluginId) {
|
|
57484
|
+
const diagnostic = this.pluginDiagnostics.get(pluginId) ?? null;
|
|
57485
|
+
const runtime2 = this.pluginRuntimes.get(pluginId) ?? null;
|
|
57486
|
+
if (!diagnostic && !runtime2)
|
|
57487
|
+
return null;
|
|
57488
|
+
const plugin = runtime2?.plugin;
|
|
57489
|
+
const listeners = runtime2 ? runtime2.disposers.filter((entry) => entry.active && entry.kind === "event").length : 0;
|
|
57490
|
+
const inputInterceptors = runtime2 ? runtime2.disposers.filter((entry) => entry.active && entry.kind === "input-interceptor").length : 0;
|
|
57491
|
+
const outputInterceptors = runtime2 ? runtime2.disposers.filter((entry) => entry.active && entry.kind === "output-interceptor").length : 0;
|
|
57492
|
+
const lifecycleHooks = runtime2 ? runtime2.disposers.filter((entry) => entry.active && entry.kind === "lifecycle-hook").length : 0;
|
|
57493
|
+
const renderHooks = runtime2 ? runtime2.disposers.filter((entry) => entry.active && entry.kind === "render-hook").length : 0;
|
|
57494
|
+
return {
|
|
57495
|
+
id: pluginId,
|
|
57496
|
+
version: plugin?.version?.trim?.() || diagnostic?.version || null,
|
|
57497
|
+
apiVersion: plugin?.apiVersion ?? (Number.isFinite(diagnostic?.apiVersion) ? diagnostic?.apiVersion : null),
|
|
57498
|
+
requires: plugin?.requires ?? diagnostic?.requires ?? null,
|
|
57499
|
+
active: runtime2 ? true : diagnostic?.active ?? false,
|
|
57500
|
+
activatedAt: runtime2?.activatedAt ?? diagnostic?.activatedAt ?? null,
|
|
57501
|
+
lastError: diagnostic?.lastError ?? null,
|
|
57502
|
+
listeners,
|
|
57503
|
+
inputInterceptors,
|
|
57504
|
+
outputInterceptors,
|
|
57505
|
+
lifecycleHooks,
|
|
57506
|
+
renderHooks
|
|
57507
|
+
};
|
|
57508
|
+
}
|
|
57509
|
+
errorToMessage(error) {
|
|
57510
|
+
if (error instanceof Error)
|
|
57511
|
+
return error.message || error.name || "Unknown error";
|
|
57512
|
+
return String(error);
|
|
57513
|
+
}
|
|
57514
|
+
onPluginEvent(event, listener) {
|
|
57515
|
+
let listeners = this.pluginListeners.get(event);
|
|
57516
|
+
if (!listeners) {
|
|
57517
|
+
listeners = new Set;
|
|
57518
|
+
this.pluginListeners.set(event, listeners);
|
|
57519
|
+
}
|
|
57520
|
+
const wrapped = listener;
|
|
57521
|
+
listeners.add(wrapped);
|
|
57522
|
+
return () => {
|
|
57523
|
+
const current = this.pluginListeners.get(event);
|
|
57524
|
+
if (!current)
|
|
57525
|
+
return;
|
|
57526
|
+
current.delete(wrapped);
|
|
57527
|
+
if (current.size === 0) {
|
|
57528
|
+
this.pluginListeners.delete(event);
|
|
57529
|
+
}
|
|
57530
|
+
};
|
|
57531
|
+
}
|
|
57532
|
+
emitPluginEvent(event, payload) {
|
|
57533
|
+
const listeners = this.pluginListeners.get(event);
|
|
57534
|
+
if (!listeners || listeners.size === 0)
|
|
57535
|
+
return;
|
|
57536
|
+
const snapshot = Array.from(listeners);
|
|
57537
|
+
for (let i3 = 0;i3 < snapshot.length; i3 += 1) {
|
|
57538
|
+
try {
|
|
57539
|
+
snapshot[i3](payload);
|
|
57540
|
+
} catch (error) {
|
|
57541
|
+
console.error(`[restty plugin] listener error (${String(event)}):`, error);
|
|
57542
|
+
}
|
|
57543
|
+
}
|
|
57544
|
+
}
|
|
57545
|
+
teardownPluginRuntime(runtime2) {
|
|
57546
|
+
for (let i3 = 0;i3 < runtime2.disposers.length; i3 += 1) {
|
|
57547
|
+
try {
|
|
57548
|
+
runtime2.disposers[i3].dispose();
|
|
57549
|
+
} catch {}
|
|
57550
|
+
}
|
|
57551
|
+
runtime2.disposers.length = 0;
|
|
57552
|
+
const cleanup = runtime2.cleanup;
|
|
57553
|
+
runtime2.cleanup = null;
|
|
57554
|
+
if (!cleanup)
|
|
57555
|
+
return;
|
|
57556
|
+
try {
|
|
57557
|
+
cleanup();
|
|
57558
|
+
} catch (error) {
|
|
57559
|
+
console.error(`[restty plugin] cleanup error (${runtime2.plugin.id}):`, error);
|
|
57560
|
+
}
|
|
57561
|
+
}
|
|
57562
|
+
normalizePluginCleanup(cleanup) {
|
|
57563
|
+
if (!cleanup)
|
|
57564
|
+
return null;
|
|
57565
|
+
if (typeof cleanup === "function")
|
|
57566
|
+
return cleanup;
|
|
57567
|
+
if (typeof cleanup === "object" && typeof cleanup.dispose === "function") {
|
|
57568
|
+
return () => cleanup.dispose();
|
|
57569
|
+
}
|
|
57570
|
+
return null;
|
|
57571
|
+
}
|
|
56764
57572
|
}
|
|
56765
57573
|
function createRestty(options) {
|
|
56766
57574
|
return new Restty(options);
|
|
56767
57575
|
}
|
|
56768
57576
|
|
|
56769
|
-
export { BOX_LINE_MAP, BOX_STYLE_NONE, BOX_STYLE_LIGHT, BOX_STYLE_HEAVY, BOX_STYLE_DOUBLE, isPrivateUse, isSpaceCp, isBoxDrawing, isBlockElement, isLegacyComputing, isPowerline, isBraille, isGraphicsElement, isSymbolCp, applyAlpha, pushRect, pushRectSnapped, pushRectBox, drawBlockElement, drawBoxDrawing, drawBraille, drawPowerline, constrainGlyphBox, RECT_SHADER, GLYPH_SHADER, initWebGPUCore, initWebGPU, initWebGL, ensureInstanceBuffer, configureContext, ensureGLInstanceBuffer, createResizeState, createScrollbarState, ResttyWasm, loadResttyWasm, createInputHandler, NERD_SYMBOL_RANGES, isNerdSymbolCodepoint, fontHeightUnits, computeCellMetrics, createGridState, updateGridState, clamp, isSymbolFont, isNerdSymbolFont, fontMaxCellSpan, fontScaleOverride, fontRasterScale, createFontEntry, resetFontEntry, createFontManagerState, fontHasGlyph, fontAdvanceUnits, glyphWidthUnits, pickFontIndexForText, tryFetchFontBuffer, tryLocalFontBuffer, loadPrimaryFontBuffer, loadFallbackFontBuffers, NERD_CONSTRAINTS, getNerdConstraint, createPtyConnection, connectPty, disconnectPty, sendPtyInput, sendPtyResize, isPtyConnected, createWebSocketPtyTransport, parseGhosttyColor, colorToFloats, colorToRgbU32, parseGhosttyTheme, listBuiltinThemeNames, isBuiltinThemeName, getBuiltinThemeSource, getBuiltinTheme, createImeState, setPreedit, clearPreedit, startComposition, updateComposition, endComposition, syncImeSelection, updateImePosition, PREEDIT_BG, PREEDIT_ACTIVE_BG, PREEDIT_FG, PREEDIT_UL, PREEDIT_CARET, ResttyPaneHandle, Restty, createRestty };
|
|
57577
|
+
export { BOX_LINE_MAP, BOX_STYLE_NONE, BOX_STYLE_LIGHT, BOX_STYLE_HEAVY, BOX_STYLE_DOUBLE, isPrivateUse, isSpaceCp, isBoxDrawing, isBlockElement, isLegacyComputing, isPowerline, isBraille, isGraphicsElement, isSymbolCp, applyAlpha, pushRect, pushRectSnapped, pushRectBox, drawBlockElement, drawBoxDrawing, drawBraille, drawPowerline, constrainGlyphBox, RECT_SHADER, GLYPH_SHADER, initWebGPUCore, initWebGPU, initWebGL, ensureInstanceBuffer, configureContext, ensureGLInstanceBuffer, createResizeState, createScrollbarState, ResttyWasm, loadResttyWasm, createInputHandler, NERD_SYMBOL_RANGES, isNerdSymbolCodepoint, fontHeightUnits, computeCellMetrics, createGridState, updateGridState, clamp, isSymbolFont, isNerdSymbolFont, fontMaxCellSpan, fontScaleOverride, fontRasterScale, createFontEntry, resetFontEntry, createFontManagerState, fontHasGlyph, fontAdvanceUnits, glyphWidthUnits, pickFontIndexForText, tryFetchFontBuffer, tryLocalFontBuffer, loadPrimaryFontBuffer, loadFallbackFontBuffers, NERD_CONSTRAINTS, getNerdConstraint, createPtyConnection, connectPty, disconnectPty, sendPtyInput, sendPtyResize, isPtyConnected, createWebSocketPtyTransport, parseGhosttyColor, colorToFloats, colorToRgbU32, parseGhosttyTheme, listBuiltinThemeNames, isBuiltinThemeName, getBuiltinThemeSource, getBuiltinTheme, createImeState, setPreedit, clearPreedit, startComposition, updateComposition, endComposition, syncImeSelection, updateImePosition, PREEDIT_BG, PREEDIT_ACTIVE_BG, PREEDIT_FG, PREEDIT_UL, PREEDIT_CARET, RESTTY_PLUGIN_API_VERSION, ResttyPaneHandle, Restty, createRestty };
|