@alchemy.run/sigil 0.0.0-alpha.4 → 0.0.0-alpha.6
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 +21 -9
- package/THIRD_PARTY_NOTICES.md +39 -1
- package/dist/Text-BobFKi74.d.ts +452 -0
- package/dist/ansi.d.ts +122 -131
- package/dist/ansi.js +86 -6
- package/dist/capabilities.d.ts +5 -0
- package/dist/capabilities.js +3 -0
- package/dist/cell-_ZVhbfl0.js +44 -0
- package/dist/color-CkbalRqK.js +2 -0
- package/dist/color-policy-BMzMwV7Q.d.ts +22 -0
- package/dist/color-policy-SVj1pYTA.js +560 -0
- package/dist/color-profile-DHhQHY55.js +36 -0
- package/dist/color-profile-u0Nhe9Nv.d.ts +97 -0
- package/dist/color.d.ts +21 -0
- package/dist/color.js +3 -0
- package/dist/cursor-position-D2LAkRG0.d.ts +7 -0
- package/dist/detect-Bh4yGP6w.d.ts +186 -0
- package/dist/detect-BuTXtY6e.js +373 -0
- package/dist/env-YVw64yZS.js +9 -0
- package/dist/escapes-CB_6CWOE.d.ts +72 -0
- package/dist/geometry-BxXOzJgo.d.ts +11 -0
- package/dist/index-DZ88EXJv.d.ts +21 -0
- package/dist/index.d.ts +143 -498
- package/dist/index.js +1026 -2244
- package/dist/osc-CCH7xDoS.js +71 -0
- package/dist/osc-Cn0fw77g.d.ts +23 -0
- package/dist/paint-C19minOS.d.ts +81 -0
- package/dist/query-vaIeGOkH.d.ts +152 -0
- package/dist/router.d.ts +392 -0
- package/dist/router.js +709 -0
- package/dist/sample-Cqw1bjUL.js +445 -0
- package/dist/screen-BOSLQ8fF.d.ts +49 -0
- package/dist/screen-CiPytswf.js +342 -0
- package/dist/screen.d.ts +5 -0
- package/dist/screen.js +5 -0
- package/dist/semantic-text-style-DIMzC7xt.js +91 -0
- package/dist/serialize-BTkAZgw1.js +79 -0
- package/dist/session-aZr9O8h3.js +665 -0
- package/dist/sgr-BhwaWAJB.js +246 -0
- package/dist/store-CgrG9K4y.d.ts +72 -0
- package/dist/string-width-CijQwpIk.js +69 -0
- package/dist/strip-BvU4toXG.js +6 -0
- package/dist/terminal.d.ts +118 -0
- package/dist/terminal.js +2 -0
- package/dist/tokenize-AjqbvtiT.js +1242 -0
- package/dist/tokenize-Dx1y_l5H.d.ts +57 -0
- package/dist/truncate-D31fhU6i.js +562 -0
- package/dist/use-focus-BzqAJi0n.js +1337 -0
- package/package.json +41 -9
- package/src/ansi/chalk.ts +5 -3
- package/src/ansi/escapes.ts +14 -0
- package/src/ansi/graphemes.ts +8 -0
- package/src/ansi/hyperlink.ts +44 -0
- package/src/ansi/index.ts +3 -1
- package/src/ansi/osc.ts +77 -0
- package/src/ansi/tokenize.ts +3 -4
- package/src/capabilities/color-policy.ts +34 -0
- package/src/capabilities/detect.ts +594 -0
- package/src/capabilities/index.ts +37 -0
- package/src/capabilities/query.ts +657 -0
- package/src/capabilities/store.ts +379 -0
- package/src/color/index.ts +3 -0
- package/src/color/paint.ts +169 -0
- package/src/color/palette.ts +48 -0
- package/src/color/sample.ts +323 -0
- package/src/color.ts +1 -0
- package/src/components/AnsiText.tsx +42 -0
- package/src/components/App.tsx +98 -10
- package/src/components/BackgroundContext.ts +2 -3
- package/src/components/Box.tsx +0 -8
- package/src/components/CursorContext.ts +1 -1
- package/src/components/Hyperlink.tsx +56 -0
- package/src/components/TerminalOscContext.ts +25 -0
- package/src/components/Text.tsx +22 -45
- package/src/components/Transform.tsx +1 -1
- package/src/dom.ts +11 -2
- package/src/global.d.ts +3 -0
- package/src/hooks/use-capabilities.ts +73 -0
- package/src/hooks/use-cursor.ts +2 -2
- package/src/hooks/use-terminal-osc.ts +59 -0
- package/src/index.ts +45 -1
- package/src/ink.tsx +213 -153
- package/src/{render-node-to-output.ts → paint-tree.ts} +75 -48
- package/src/reconciler.ts +24 -3
- package/src/render-background.ts +36 -15
- package/src/render-border.ts +94 -61
- package/src/render-frame.ts +83 -0
- package/src/render-to-string.ts +21 -6
- package/src/render.ts +15 -6
- package/src/router/components.tsx +343 -0
- package/src/router/context.ts +41 -0
- package/src/router/history.ts +194 -0
- package/src/router/hooks.tsx +391 -0
- package/src/router/index.ts +34 -0
- package/src/router/matcher.ts +571 -0
- package/src/screen/ansi.ts +184 -0
- package/src/screen/canvas.ts +160 -0
- package/src/screen/cell.ts +138 -0
- package/src/screen/color-profile.ts +47 -0
- package/src/screen/geometry.ts +9 -0
- package/src/screen/index.ts +6 -0
- package/src/screen/screen.ts +305 -0
- package/src/screen/serialize.ts +129 -0
- package/src/screen.ts +1 -0
- package/src/semantic-text-style.ts +118 -0
- package/src/squash-text-nodes.ts +2 -5
- package/src/structured-text.ts +325 -0
- package/src/styles.ts +19 -14
- package/src/terminal/index.ts +2 -0
- package/src/terminal/inline-presenter.ts +120 -0
- package/src/terminal/input.ts +86 -0
- package/src/terminal/render-scheduler.ts +37 -0
- package/src/terminal/screen-presenter.ts +188 -0
- package/src/terminal/session.ts +407 -0
- package/src/terminal.ts +1 -0
- package/src/testing/browser.ts +588 -0
- package/src/testing/emulators.ts +205 -0
- package/src/testing/explorer-app/index.html +12 -0
- package/src/testing/explorer-app/main.ts +381 -0
- package/src/testing/explorer-app/style.css +194 -0
- package/src/testing/explorer-app/tsconfig.json +15 -0
- package/src/testing/explorer-app/vite-env.d.ts +1 -0
- package/src/testing/index.ts +26 -0
- package/src/testing/keys.ts +56 -0
- package/src/testing/live.ts +85 -0
- package/src/testing/matchers.ts +70 -0
- package/src/testing/public.ts +94 -0
- package/src/testing/terminal.ts +349 -0
- package/src/testing/vitest.ts +157 -0
- package/src/transform-adapter.ts +14 -0
- package/src/wrap-text.ts +4 -0
- package/dist/sgr-CMfEpjSk.d.ts +0 -91
- package/dist/truncate-Cr6xVFMa.js +0 -2330
- package/src/ansi/supports-color.ts +0 -207
- package/src/colorize.ts +0 -60
- package/src/log-update.ts +0 -370
- package/src/output.ts +0 -308
- package/src/renderer.ts +0 -73
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
//#region src/ansi/escapes.ts
|
|
2
|
+
const ESC = "\x1B";
|
|
3
|
+
const BEL = "\x07";
|
|
4
|
+
const DEL = "";
|
|
5
|
+
/** Control Sequence Introducer. */
|
|
6
|
+
const CSI = `[`;
|
|
7
|
+
/** Operating System Command. */
|
|
8
|
+
const OSC = `]`;
|
|
9
|
+
/** String Terminator. */
|
|
10
|
+
const ST = `\\`;
|
|
11
|
+
/** Single-byte C1 forms of CSI and ST. */
|
|
12
|
+
const C1_CSI = "";
|
|
13
|
+
const C1_ST = "";
|
|
14
|
+
const sep = ";";
|
|
15
|
+
const cursorTo = (x, y) => {
|
|
16
|
+
if (typeof y !== "number") return CSI + (x + 1) + "G";
|
|
17
|
+
return CSI + (y + 1) + sep + (x + 1) + "H";
|
|
18
|
+
};
|
|
19
|
+
const cursorUp = (count = 1) => CSI + count + "A";
|
|
20
|
+
const cursorDown = (count = 1) => CSI + count + "B";
|
|
21
|
+
const cursorLeft = CSI + "G";
|
|
22
|
+
const cursorNextLine = CSI + "E";
|
|
23
|
+
const eraseEndLine = CSI + "K";
|
|
24
|
+
const eraseLine = CSI + "2K";
|
|
25
|
+
const eraseScreen = CSI + "2J";
|
|
26
|
+
const eraseLines = (count) => {
|
|
27
|
+
let clear = "";
|
|
28
|
+
for (let i = 0; i < count; i++) clear += eraseLine + (i < count - 1 ? cursorUp() : "");
|
|
29
|
+
if (count) clear += cursorLeft;
|
|
30
|
+
return clear;
|
|
31
|
+
};
|
|
32
|
+
const clearTerminal = `${eraseScreen}${CSI}3J${CSI}H`;
|
|
33
|
+
const enterAlternativeScreen = CSI + "?1049h";
|
|
34
|
+
const exitAlternativeScreen = CSI + "?1049l";
|
|
35
|
+
const cursorShow = CSI + "?25h";
|
|
36
|
+
const cursorHide = CSI + "?25l";
|
|
37
|
+
const cursorShape = (shape, blinking = true) => {
|
|
38
|
+
const value = {
|
|
39
|
+
block: blinking ? 1 : 2,
|
|
40
|
+
underline: blinking ? 3 : 4,
|
|
41
|
+
bar: blinking ? 5 : 6
|
|
42
|
+
}[shape];
|
|
43
|
+
return `${CSI}${value} q`;
|
|
44
|
+
};
|
|
45
|
+
const cursorColor = (color) => `${OSC}12;${color}`;
|
|
46
|
+
const resetCursorColor = `${OSC}112`;
|
|
47
|
+
const enableBracketedPaste = CSI + "?2004h";
|
|
48
|
+
const disableBracketedPaste = CSI + "?2004l";
|
|
49
|
+
const pasteStart = CSI + "200~";
|
|
50
|
+
const pasteEnd = CSI + "201~";
|
|
51
|
+
const bsu = CSI + "?2026h";
|
|
52
|
+
const esu = CSI + "?2026l";
|
|
53
|
+
const kittyQuery = CSI + "?u";
|
|
54
|
+
const pushKittyKeyboard = (flags) => `${CSI}>${flags}u`;
|
|
55
|
+
const popKittyKeyboard = CSI + "<u";
|
|
56
|
+
const link = (text, url) => [
|
|
57
|
+
OSC,
|
|
58
|
+
"8",
|
|
59
|
+
sep,
|
|
60
|
+
sep,
|
|
61
|
+
url,
|
|
62
|
+
"\x07",
|
|
63
|
+
text,
|
|
64
|
+
OSC,
|
|
65
|
+
"8",
|
|
66
|
+
sep,
|
|
67
|
+
sep,
|
|
68
|
+
"\x07"
|
|
69
|
+
].join("");
|
|
70
|
+
const ansiEscapes = {
|
|
71
|
+
cursorTo,
|
|
72
|
+
cursorUp,
|
|
73
|
+
cursorDown,
|
|
74
|
+
cursorLeft,
|
|
75
|
+
cursorNextLine,
|
|
76
|
+
eraseEndLine,
|
|
77
|
+
eraseLine,
|
|
78
|
+
eraseScreen,
|
|
79
|
+
eraseLines,
|
|
80
|
+
clearTerminal,
|
|
81
|
+
enterAlternativeScreen,
|
|
82
|
+
exitAlternativeScreen,
|
|
83
|
+
cursorShow,
|
|
84
|
+
cursorHide,
|
|
85
|
+
cursorShape,
|
|
86
|
+
cursorColor,
|
|
87
|
+
resetCursorColor,
|
|
88
|
+
enableBracketedPaste,
|
|
89
|
+
disableBracketedPaste,
|
|
90
|
+
pasteStart,
|
|
91
|
+
pasteEnd,
|
|
92
|
+
bsu,
|
|
93
|
+
esu,
|
|
94
|
+
kittyQuery,
|
|
95
|
+
pushKittyKeyboard,
|
|
96
|
+
popKittyKeyboard,
|
|
97
|
+
link
|
|
98
|
+
};
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/ansi/sgr.ts
|
|
101
|
+
const ANSI_BACKGROUND_OFFSET = 10;
|
|
102
|
+
const wrapAnsi16 = (offset = 0) => (code) => `${CSI}${code + offset}m`;
|
|
103
|
+
const wrapAnsi256 = (offset = 0) => (code) => `${CSI}${38 + offset};5;${code}m`;
|
|
104
|
+
const wrapAnsi16m = (offset = 0) => (red, green, blue) => `${CSI}${38 + offset};2;${red};${green};${blue}m`;
|
|
105
|
+
const modifierCodes = {
|
|
106
|
+
reset: [0, 0],
|
|
107
|
+
bold: [1, 22],
|
|
108
|
+
dim: [2, 22],
|
|
109
|
+
italic: [3, 23],
|
|
110
|
+
underline: [4, 24],
|
|
111
|
+
overline: [53, 55],
|
|
112
|
+
inverse: [7, 27],
|
|
113
|
+
hidden: [8, 28],
|
|
114
|
+
strikethrough: [9, 29]
|
|
115
|
+
};
|
|
116
|
+
const colorCodes = {
|
|
117
|
+
black: [30, 39],
|
|
118
|
+
red: [31, 39],
|
|
119
|
+
green: [32, 39],
|
|
120
|
+
yellow: [33, 39],
|
|
121
|
+
blue: [34, 39],
|
|
122
|
+
magenta: [35, 39],
|
|
123
|
+
cyan: [36, 39],
|
|
124
|
+
white: [37, 39],
|
|
125
|
+
blackBright: [90, 39],
|
|
126
|
+
gray: [90, 39],
|
|
127
|
+
grey: [90, 39],
|
|
128
|
+
redBright: [91, 39],
|
|
129
|
+
greenBright: [92, 39],
|
|
130
|
+
yellowBright: [93, 39],
|
|
131
|
+
blueBright: [94, 39],
|
|
132
|
+
magentaBright: [95, 39],
|
|
133
|
+
cyanBright: [96, 39],
|
|
134
|
+
whiteBright: [97, 39]
|
|
135
|
+
};
|
|
136
|
+
const bgColorCodes = {
|
|
137
|
+
bgBlack: [40, 49],
|
|
138
|
+
bgRed: [41, 49],
|
|
139
|
+
bgGreen: [42, 49],
|
|
140
|
+
bgYellow: [43, 49],
|
|
141
|
+
bgBlue: [44, 49],
|
|
142
|
+
bgMagenta: [45, 49],
|
|
143
|
+
bgCyan: [46, 49],
|
|
144
|
+
bgWhite: [47, 49],
|
|
145
|
+
bgBlackBright: [100, 49],
|
|
146
|
+
bgGray: [100, 49],
|
|
147
|
+
bgGrey: [100, 49],
|
|
148
|
+
bgRedBright: [101, 49],
|
|
149
|
+
bgGreenBright: [102, 49],
|
|
150
|
+
bgYellowBright: [103, 49],
|
|
151
|
+
bgBlueBright: [104, 49],
|
|
152
|
+
bgMagentaBright: [105, 49],
|
|
153
|
+
bgCyanBright: [106, 49],
|
|
154
|
+
bgWhiteBright: [107, 49]
|
|
155
|
+
};
|
|
156
|
+
const modifierNames = Object.keys(modifierCodes);
|
|
157
|
+
const foregroundColorNames = Object.keys(colorCodes);
|
|
158
|
+
const backgroundColorNames = Object.keys(bgColorCodes);
|
|
159
|
+
const toPairs = (codes) => {
|
|
160
|
+
const result = {};
|
|
161
|
+
for (const [name, [open, close]] of Object.entries(codes)) result[name] = {
|
|
162
|
+
open: `${CSI}${open}m`,
|
|
163
|
+
close: `${CSI}${close}m`
|
|
164
|
+
};
|
|
165
|
+
return result;
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
Named SGR styles as `{open, close}` escape sequence pairs.
|
|
169
|
+
*/
|
|
170
|
+
const styles = {
|
|
171
|
+
...toPairs(modifierCodes),
|
|
172
|
+
...toPairs(colorCodes),
|
|
173
|
+
...toPairs(bgColorCodes)
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
Raw SGR code numbers: open code → close code.
|
|
177
|
+
*/
|
|
178
|
+
const codes = new Map([
|
|
179
|
+
...Object.values(modifierCodes),
|
|
180
|
+
...Object.values(colorCodes),
|
|
181
|
+
...Object.values(bgColorCodes)
|
|
182
|
+
].map(([open, close]) => [open, close]));
|
|
183
|
+
const foreground = {
|
|
184
|
+
close: `${CSI}39m`,
|
|
185
|
+
ansi: wrapAnsi16(),
|
|
186
|
+
ansi256: wrapAnsi256(),
|
|
187
|
+
ansi16m: wrapAnsi16m()
|
|
188
|
+
};
|
|
189
|
+
const background = {
|
|
190
|
+
close: `${CSI}49m`,
|
|
191
|
+
ansi: wrapAnsi16(ANSI_BACKGROUND_OFFSET),
|
|
192
|
+
ansi256: wrapAnsi256(ANSI_BACKGROUND_OFFSET),
|
|
193
|
+
ansi16m: wrapAnsi16m(ANSI_BACKGROUND_OFFSET)
|
|
194
|
+
};
|
|
195
|
+
const rgbToAnsi256 = (red, green, blue) => {
|
|
196
|
+
if (red === green && green === blue) {
|
|
197
|
+
if (red < 8) return 16;
|
|
198
|
+
if (red > 248) return 231;
|
|
199
|
+
return Math.round((red - 8) / 247 * 24) + 232;
|
|
200
|
+
}
|
|
201
|
+
return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
|
|
202
|
+
};
|
|
203
|
+
const hexToRgb = (hex) => {
|
|
204
|
+
const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex);
|
|
205
|
+
if (!matches) return [
|
|
206
|
+
0,
|
|
207
|
+
0,
|
|
208
|
+
0
|
|
209
|
+
];
|
|
210
|
+
let [colorString] = matches;
|
|
211
|
+
if (colorString.length === 3) colorString = colorString.replaceAll(/./g, "$&$&");
|
|
212
|
+
const integer = Number.parseInt(colorString, 16);
|
|
213
|
+
return [
|
|
214
|
+
integer >> 16 & 255,
|
|
215
|
+
integer >> 8 & 255,
|
|
216
|
+
integer & 255
|
|
217
|
+
];
|
|
218
|
+
};
|
|
219
|
+
const hexToAnsi256 = (hex) => rgbToAnsi256(...hexToRgb(hex));
|
|
220
|
+
const ansi256ToAnsi = (code) => {
|
|
221
|
+
if (code < 8) return 30 + code;
|
|
222
|
+
if (code < 16) return 90 + (code - 8);
|
|
223
|
+
let red;
|
|
224
|
+
let green;
|
|
225
|
+
let blue;
|
|
226
|
+
if (code >= 232) {
|
|
227
|
+
red = ((code - 232) * 10 + 8) / 255;
|
|
228
|
+
green = red;
|
|
229
|
+
blue = red;
|
|
230
|
+
} else {
|
|
231
|
+
code -= 16;
|
|
232
|
+
const remainder = code % 36;
|
|
233
|
+
red = Math.floor(code / 36) / 5;
|
|
234
|
+
green = Math.floor(remainder / 6) / 5;
|
|
235
|
+
blue = remainder % 6 / 5;
|
|
236
|
+
}
|
|
237
|
+
const value = Math.max(red, green, blue) * 2;
|
|
238
|
+
if (value === 0) return 30;
|
|
239
|
+
let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
|
|
240
|
+
if (value === 2) result += 60;
|
|
241
|
+
return result;
|
|
242
|
+
};
|
|
243
|
+
const rgbToAnsi = (red, green, blue) => ansi256ToAnsi(rgbToAnsi256(red, green, blue));
|
|
244
|
+
const hexToAnsi = (hex) => ansi256ToAnsi(hexToAnsi256(hex));
|
|
245
|
+
//#endregion
|
|
246
|
+
export { cursorShape as A, eraseScreen as B, bsu as C, cursorHide as D, cursorDown as E, enableBracketedPaste as F, pasteEnd as G, exitAlternativeScreen as H, enterAlternativeScreen as I, pushKittyKeyboard as J, pasteStart as K, eraseEndLine as L, cursorTo as M, cursorUp as N, cursorLeft as O, disableBracketedPaste as P, eraseLine as R, ansiEscapes as S, cursorColor as T, kittyQuery as U, esu as V, link as W, resetCursorColor as Y, CSI as _, foreground as a, OSC as b, hexToAnsi256 as c, rgbToAnsi as d, rgbToAnsi256 as f, C1_ST as g, C1_CSI as h, codes as i, cursorShow as j, cursorNextLine as k, hexToRgb as l, BEL as m, background as n, foregroundColorNames as o, styles as p, popKittyKeyboard as q, backgroundColorNames as r, hexToAnsi as s, ansi256ToAnsi as t, modifierNames as u, DEL as v, clearTerminal as w, ST as x, ESC as y, eraseLines as z };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { t as Capabilities } from "./detect-Bh4yGP6w.js";
|
|
2
|
+
//#region src/stream.d.ts
|
|
3
|
+
type OutputStream = NodeJS.WritableStream & {
|
|
4
|
+
isTTY?: boolean;
|
|
5
|
+
columns?: number;
|
|
6
|
+
rows?: number;
|
|
7
|
+
destroyed?: boolean;
|
|
8
|
+
writableEnded?: boolean;
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/capabilities/store.d.ts
|
|
12
|
+
type StoreStdin = NodeJS.ReadableStream & {
|
|
13
|
+
isTTY?: boolean;
|
|
14
|
+
isRaw?: boolean;
|
|
15
|
+
setRawMode?: (mode: boolean) => void;
|
|
16
|
+
};
|
|
17
|
+
type StoreStdout = OutputStream;
|
|
18
|
+
type CapabilitiesStore = {
|
|
19
|
+
/**
|
|
20
|
+
The current snapshot: environment-derived detection merged with every
|
|
21
|
+
query answer received so far. Size is always fresh; the object identity
|
|
22
|
+
only changes when something actually changed, so it's safe to compare.
|
|
23
|
+
*/
|
|
24
|
+
readonly current: Capabilities;
|
|
25
|
+
/**
|
|
26
|
+
Asks the terminal. The first call runs the full query; subsequent calls
|
|
27
|
+
re-ask only the dynamic questions (theme colors, pixel geometry) and
|
|
28
|
+
merge over the cached answers. No-op outside a TTY. Resolves with the
|
|
29
|
+
updated snapshot.
|
|
30
|
+
*/
|
|
31
|
+
query: () => Promise<Capabilities>;
|
|
32
|
+
/**
|
|
33
|
+
Subscribes to snapshot changes: query answers arriving, terminal resizes
|
|
34
|
+
(including in-band pixel geometry), color scheme switches, and window
|
|
35
|
+
focus changes. While subscribers exist (and a report feed is available),
|
|
36
|
+
the store enables the supported report modes on the terminal and disables
|
|
37
|
+
them again on the last unsubscribe. Returns an unsubscribe function.
|
|
38
|
+
*/
|
|
39
|
+
subscribe: (listener: (capabilities: Capabilities) => void, options?: {
|
|
40
|
+
resizes?: boolean;
|
|
41
|
+
}) => () => void;
|
|
42
|
+
/**
|
|
43
|
+
Feeds one parsed escape sequence from an input pipeline into the store.
|
|
44
|
+
Returns `true` when the sequence was an unsolicited terminal report
|
|
45
|
+
(color scheme, focus, in-band resize) and was consumed. Ink calls this
|
|
46
|
+
for every escape sequence it reads; standalone apps that read stdin
|
|
47
|
+
themselves can forward unrecognized sequences here.
|
|
48
|
+
*/
|
|
49
|
+
ingest: (sequence: string) => boolean;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
The capabilities store for a stream pair. Stores are cached per stdout, so
|
|
53
|
+
standalone code and Ink components observing the same terminal share one
|
|
54
|
+
snapshot and one set of query answers.
|
|
55
|
+
*/
|
|
56
|
+
declare const getCapabilities: (stdin?: StoreStdin, stdout?: StoreStdout) => CapabilitiesStore;
|
|
57
|
+
/**
|
|
58
|
+
The process's own terminal — the store for `process.stdin`/`process.stdout`.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { capabilities } from "@alchemy.run/sigil/capabilities";
|
|
62
|
+
|
|
63
|
+
capabilities.current.supports.hyperlinks;
|
|
64
|
+
const fresh = await capabilities.query();
|
|
65
|
+
const unsubscribe = capabilities.subscribe((caps) => {
|
|
66
|
+
console.log(caps.size, caps.theme.appearance);
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
*/
|
|
70
|
+
declare const capabilities: CapabilitiesStore;
|
|
71
|
+
//#endregion
|
|
72
|
+
export { OutputStream as i, capabilities as n, getCapabilities as r, CapabilitiesStore as t };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { N as isWideNotCJKTNotEmoji, k as isFullWidth } from "./tokenize-AjqbvtiT.js";
|
|
2
|
+
//#region src/ansi/string-width.ts
|
|
3
|
+
const getCodePointsLength = (input) => {
|
|
4
|
+
let length = 0;
|
|
5
|
+
for (const _ of input) length += 1;
|
|
6
|
+
return length;
|
|
7
|
+
};
|
|
8
|
+
const ANSI_RE = /[\u001b\u009b][[()#;?]*[0-9;:]*[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
9
|
+
const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
10
|
+
const CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy;
|
|
11
|
+
const TAB_RE = /\t{1,1000}/y;
|
|
12
|
+
const EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy;
|
|
13
|
+
const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
14
|
+
const MODIFIER_RE = /\p{M}+/gu;
|
|
15
|
+
const ANSI_WIDTH = 0;
|
|
16
|
+
const CONTROL_WIDTH = 0;
|
|
17
|
+
const TAB_WIDTH = 8;
|
|
18
|
+
const EMOJI_WIDTH = 2;
|
|
19
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
20
|
+
const REGULAR_WIDTH = 1;
|
|
21
|
+
const WIDE_WIDTH = 2;
|
|
22
|
+
const PARSE_BLOCKS = [
|
|
23
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
24
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
25
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
26
|
+
[TAB_RE, TAB_WIDTH],
|
|
27
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
28
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
29
|
+
];
|
|
30
|
+
const stringWidth = (input) => {
|
|
31
|
+
let indexPrev = 0;
|
|
32
|
+
let index = 0;
|
|
33
|
+
const length = input.length;
|
|
34
|
+
let unmatchedStart = 0;
|
|
35
|
+
let unmatchedEnd = 0;
|
|
36
|
+
let width = 0;
|
|
37
|
+
outer: while (true) {
|
|
38
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
39
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
40
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
41
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
42
|
+
width += isFullWidth(codePoint) ? FULL_WIDTH_WIDTH : isWideNotCJKTNotEmoji(codePoint) ? WIDE_WIDTH : REGULAR_WIDTH;
|
|
43
|
+
}
|
|
44
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
45
|
+
}
|
|
46
|
+
if (index >= length) break;
|
|
47
|
+
for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
|
|
48
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
49
|
+
BLOCK_RE.lastIndex = index;
|
|
50
|
+
if (BLOCK_RE.test(input)) {
|
|
51
|
+
const lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
52
|
+
width += lengthExtra * BLOCK_WIDTH;
|
|
53
|
+
unmatchedStart = indexPrev;
|
|
54
|
+
unmatchedEnd = index;
|
|
55
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
56
|
+
continue outer;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
index += 1;
|
|
60
|
+
}
|
|
61
|
+
return width;
|
|
62
|
+
};
|
|
63
|
+
const widestLine = (text) => {
|
|
64
|
+
let lineWidth = 0;
|
|
65
|
+
for (const line of text.split("\n")) lineWidth = Math.max(lineWidth, stringWidth(line));
|
|
66
|
+
return lineWidth;
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
export { widestLine as n, stringWidth as t };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { stripVTControlCharacters } from "node:util";
|
|
2
|
+
//#region src/ansi/strip.ts
|
|
3
|
+
const colonSgrRegex = /(?:\u001B\[|\u009B)[\d;]*:[\d;:]*m/g;
|
|
4
|
+
const stripAnsi = (input) => stripVTControlCharacters(input.replaceAll(colonSgrRegex, ""));
|
|
5
|
+
//#endregion
|
|
6
|
+
export { stripAnsi as t };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { a as CursorShape } from "./escapes-CB_6CWOE.js";
|
|
2
|
+
import { n as TerminalProgressState, t as ClipboardSelection } from "./osc-Cn0fw77g.js";
|
|
3
|
+
import { i as OutputStream, t as CapabilitiesStore } from "./store-CgrG9K4y.js";
|
|
4
|
+
import { t as ColorProfile } from "./color-profile-u0Nhe9Nv.js";
|
|
5
|
+
import { t as ColorPolicy } from "./color-policy-BMzMwV7Q.js";
|
|
6
|
+
import { n as Screen } from "./screen-BOSLQ8fF.js";
|
|
7
|
+
import { t as CursorPosition } from "./cursor-position-D2LAkRG0.js";
|
|
8
|
+
//#region src/input-parser.d.ts
|
|
9
|
+
type InputEvent = string | {
|
|
10
|
+
readonly paste: string;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/terminal/input.d.ts
|
|
14
|
+
type MouseButton = "left" | "middle" | "right" | "none" | "wheel-up" | "wheel-down";
|
|
15
|
+
type TerminalMouseEvent = {
|
|
16
|
+
readonly type: "press" | "release" | "move" | "wheel";
|
|
17
|
+
readonly x: number;
|
|
18
|
+
readonly y: number;
|
|
19
|
+
readonly button: MouseButton;
|
|
20
|
+
readonly shift: boolean;
|
|
21
|
+
readonly alt: boolean;
|
|
22
|
+
readonly ctrl: boolean;
|
|
23
|
+
};
|
|
24
|
+
/** Stateful stdin decoder that separates terminal reports from application input. */
|
|
25
|
+
declare class TerminalInput {
|
|
26
|
+
#private;
|
|
27
|
+
constructor(capabilities: CapabilitiesStore);
|
|
28
|
+
push(chunk: string): InputEvent[];
|
|
29
|
+
subscribeMouse(listener: (event: TerminalMouseEvent) => void): () => void;
|
|
30
|
+
hasPendingEscape(): boolean;
|
|
31
|
+
flushPendingEscape(): string | undefined;
|
|
32
|
+
reset(): void;
|
|
33
|
+
}
|
|
34
|
+
declare function parseMouseEvent(sequence: string): TerminalMouseEvent | undefined;
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/terminal/session.d.ts
|
|
37
|
+
type TerminalSessionOptions = {
|
|
38
|
+
readonly stdin: NodeJS.ReadableStream;
|
|
39
|
+
readonly stdout: OutputStream;
|
|
40
|
+
readonly stderr: OutputStream;
|
|
41
|
+
readonly colorPolicy?: ColorPolicy;
|
|
42
|
+
readonly onCapabilitiesChange?: () => void;
|
|
43
|
+
};
|
|
44
|
+
type TerminalMode = {
|
|
45
|
+
readonly id: string;
|
|
46
|
+
readonly enable: string;
|
|
47
|
+
readonly disable: string;
|
|
48
|
+
};
|
|
49
|
+
type TerminalCursor = {
|
|
50
|
+
readonly position?: CursorPosition;
|
|
51
|
+
readonly visible: boolean;
|
|
52
|
+
readonly shape: CursorShape;
|
|
53
|
+
readonly blinking: boolean;
|
|
54
|
+
readonly color?: string;
|
|
55
|
+
};
|
|
56
|
+
/** Instance-scoped terminal state and lifecycle ownership. */
|
|
57
|
+
declare class TerminalSession {
|
|
58
|
+
#private;
|
|
59
|
+
readonly stdin: NodeJS.ReadableStream;
|
|
60
|
+
readonly stdout: OutputStream;
|
|
61
|
+
readonly stderr: OutputStream;
|
|
62
|
+
readonly capabilities: CapabilitiesStore;
|
|
63
|
+
readonly input: TerminalInput;
|
|
64
|
+
cursor: TerminalCursor;
|
|
65
|
+
suspended: boolean;
|
|
66
|
+
alternateScreen: boolean;
|
|
67
|
+
inlineScreen: boolean;
|
|
68
|
+
constructor(options: TerminalSessionOptions);
|
|
69
|
+
get colorProfile(): ColorProfile;
|
|
70
|
+
/** Encodes a structured frame at the terminal boundary. */
|
|
71
|
+
encode(screen: Screen): string;
|
|
72
|
+
present(screen: Screen, options?: {
|
|
73
|
+
readonly fullscreen?: boolean;
|
|
74
|
+
readonly forceRewrite?: boolean;
|
|
75
|
+
}): boolean;
|
|
76
|
+
willPresent(screen: Screen, options?: {
|
|
77
|
+
readonly fullscreen?: boolean;
|
|
78
|
+
readonly forceRewrite?: boolean;
|
|
79
|
+
}): boolean;
|
|
80
|
+
clearFrame(): void;
|
|
81
|
+
resetFrame(): void;
|
|
82
|
+
finishFrame(): void;
|
|
83
|
+
setColorPolicy(policy: ColorPolicy): void;
|
|
84
|
+
/** Writes through the session and tracks callback-based backpressure completion. */
|
|
85
|
+
write(data: string): boolean;
|
|
86
|
+
flush(): Promise<void>;
|
|
87
|
+
/** Copy text through OSC 52, including tmux passthrough when required. */
|
|
88
|
+
copyToClipboard(text: string, selection?: ClipboardSelection): boolean;
|
|
89
|
+
setTitle(title: string): boolean;
|
|
90
|
+
publishTitle(owner: symbol, title?: string): boolean;
|
|
91
|
+
setWorkingDirectory(directory: URL | string): boolean;
|
|
92
|
+
notify(title: string): boolean;
|
|
93
|
+
setPointerShape(shape: string): boolean;
|
|
94
|
+
publishProgress(owner: symbol, state: TerminalProgressState, value?: number): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Update terminal-native progress. Active progress is reset during cleanup
|
|
97
|
+
* so a completed or failed process cannot leave a stale terminal indicator.
|
|
98
|
+
*/
|
|
99
|
+
setProgress(state: TerminalProgressState, value?: number): boolean;
|
|
100
|
+
enableMode(mode: TerminalMode): void;
|
|
101
|
+
enableMode(enable: string, disable: string): void;
|
|
102
|
+
disableMode(idOrDisable: string): void;
|
|
103
|
+
setCursor(position: CursorPosition | undefined): void;
|
|
104
|
+
setCursorAppearance(options: {
|
|
105
|
+
readonly visible?: boolean;
|
|
106
|
+
readonly shape?: CursorShape;
|
|
107
|
+
readonly blinking?: boolean;
|
|
108
|
+
readonly color?: string | null;
|
|
109
|
+
}): void;
|
|
110
|
+
setAlternateScreen(enabled: boolean, options?: {
|
|
111
|
+
hideCursor?: boolean;
|
|
112
|
+
}): void;
|
|
113
|
+
beginSuspension(): void;
|
|
114
|
+
resume(): void;
|
|
115
|
+
cleanup(): void;
|
|
116
|
+
}
|
|
117
|
+
//#endregion
|
|
118
|
+
export { MouseButton, TerminalCursor, TerminalInput, TerminalMode, TerminalMouseEvent, TerminalSession, TerminalSessionOptions, parseMouseEvent };
|
package/dist/terminal.js
ADDED