@alchemy.run/sigil 0.0.0-alpha.1 → 0.0.0-alpha.2
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 +299 -299
- package/dist/ansi.d.ts +223 -0
- package/dist/ansi.js +2 -0
- package/dist/{devtools-QpCMm9JH.mjs → devtools-BhYGjb7h.js} +1 -1
- package/dist/index-DDVME65c.d.ts +919 -0
- package/dist/index.d.ts +1657 -0
- package/dist/index.js +4643 -0
- package/dist/sgr-CMfEpjSk.d.ts +91 -0
- package/dist/truncate-CBiyyZzw.js +2156 -0
- package/dist/yoga-5jKhYCJC.js +3465 -0
- package/dist/yoga.d.ts +2 -0
- package/dist/yoga.js +2 -0
- package/package.json +37 -17
- package/src/ansi/chalk.ts +179 -0
- package/src/ansi/cursor.ts +48 -0
- package/src/ansi/east-asian-width.ts +215 -0
- package/src/ansi/escapes.ts +128 -0
- package/src/ansi/index.ts +27 -0
- package/src/ansi/sgr.ts +237 -0
- package/src/ansi/slice.ts +43 -0
- package/src/ansi/string-width.ts +236 -0
- package/src/ansi/strip.ts +33 -0
- package/src/ansi/supports-color.ts +213 -0
- package/src/ansi/tokenize.ts +453 -0
- package/src/ansi/truncate.ts +194 -0
- package/src/ansi/widest-line.ts +12 -0
- package/src/ansi/wrap.ts +766 -0
- package/src/ansi-tokenizer.ts +510 -0
- package/src/auto-bind.ts +41 -0
- package/src/boxes.ts +100 -0
- package/src/code-excerpt.ts +39 -0
- package/src/colorize.ts +60 -0
- package/src/components/AccessibilityContext.ts +5 -0
- package/src/components/AnimationContext.ts +24 -0
- package/src/components/App.tsx +781 -0
- package/src/components/AppContext.ts +111 -0
- package/src/components/BackgroundContext.ts +8 -0
- package/src/components/Box.tsx +116 -0
- package/src/components/CursorContext.ts +19 -0
- package/src/components/ErrorBoundary.tsx +38 -0
- package/src/components/ErrorOverview.tsx +133 -0
- package/src/components/FocusContext.ts +30 -0
- package/src/components/Newline.tsx +15 -0
- package/src/components/Spacer.tsx +10 -0
- package/src/components/Static.tsx +59 -0
- package/src/components/StderrContext.ts +26 -0
- package/src/components/StdinContext.ts +49 -0
- package/src/components/StdoutContext.ts +28 -0
- package/src/components/Text.tsx +144 -0
- package/src/components/Transform.tsx +37 -0
- package/src/cursor-position.ts +103 -0
- package/src/devtools-window-polyfill.ts +73 -0
- package/src/devtools.ts +43 -0
- package/src/dom.ts +292 -0
- package/src/get-max-width.ts +11 -0
- package/src/global.d.ts +36 -0
- package/src/hooks/use-animation.ts +142 -0
- package/src/hooks/use-app.ts +8 -0
- package/src/hooks/use-box-metrics.ts +134 -0
- package/src/hooks/use-cursor.ts +33 -0
- package/src/hooks/use-focus-manager.ts +62 -0
- package/src/hooks/use-focus.ts +83 -0
- package/src/hooks/use-input.ts +267 -0
- package/src/hooks/use-is-screen-reader-enabled.ts +12 -0
- package/src/hooks/use-paste.ts +78 -0
- package/src/hooks/use-stderr.ts +8 -0
- package/src/hooks/use-stdin.ts +10 -0
- package/src/hooks/use-stdout.ts +8 -0
- package/src/hooks/use-window-size.ts +41 -0
- package/src/indent-string.ts +16 -0
- package/src/index.ts +44 -0
- package/src/ink.tsx +1506 -0
- package/src/input-parser.ts +283 -0
- package/src/instances.ts +9 -0
- package/src/is-in-ci.ts +7 -0
- package/src/kitty-keyboard.ts +57 -0
- package/src/log-update.ts +370 -0
- package/src/measure-element.ts +62 -0
- package/src/measure-text.ts +31 -0
- package/src/output.ts +308 -0
- package/src/parse-keypress.ts +516 -0
- package/src/parse-stack-line.ts +139 -0
- package/src/patch-console.ts +62 -0
- package/src/quick-lru.ts +85 -0
- package/src/reconciler.ts +451 -0
- package/src/render-background.ts +38 -0
- package/src/render-border.ts +134 -0
- package/src/render-node-to-output.ts +191 -0
- package/src/render-to-string.ts +131 -0
- package/src/render.ts +276 -0
- package/src/renderer.ts +73 -0
- package/src/sanitize-ansi.ts +33 -0
- package/src/signal-exit.ts +107 -0
- package/src/squash-text-nodes.ts +40 -0
- package/src/stream.ts +30 -0
- package/src/styles.ts +748 -0
- package/src/terminal-size.ts +57 -0
- package/src/throttle.ts +73 -0
- package/src/types.ts +15 -0
- package/src/utils.ts +40 -0
- package/src/wrap-text.ts +50 -0
- package/src/write-synchronized.ts +9 -0
- package/src/yoga/config.ts +57 -0
- package/src/yoga/core/absoluteLayout.ts +626 -0
- package/src/yoga/core/baseline.ts +66 -0
- package/src/yoga/core/cache.ts +136 -0
- package/src/yoga/core/calculateLayout.ts +2920 -0
- package/src/yoga/core/config.ts +104 -0
- package/src/yoga/core/flexLine.ts +177 -0
- package/src/yoga/core/helpers.ts +293 -0
- package/src/yoga/core/layoutResults.ts +167 -0
- package/src/yoga/core/node.ts +611 -0
- package/src/yoga/core/numeric.ts +44 -0
- package/src/yoga/core/pixelGrid.ts +151 -0
- package/src/yoga/core/style.ts +887 -0
- package/src/yoga/core/types.ts +224 -0
- package/src/yoga/generated/YGEnums.ts +263 -0
- package/src/yoga/index.ts +19 -0
- package/src/yoga/node.ts +1140 -0
- package/dist/index.d.mts +0 -2379
- package/dist/index.mjs +0 -10072
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { ESC, pasteStart, pasteEnd } from "./ansi/escapes.ts";
|
|
2
|
+
|
|
3
|
+
const escape = ESC;
|
|
4
|
+
|
|
5
|
+
export type InputEvent = string | { readonly paste: string };
|
|
6
|
+
|
|
7
|
+
type ParsedInput = {
|
|
8
|
+
readonly events: InputEvent[];
|
|
9
|
+
readonly pending: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
type ParsedSequence =
|
|
13
|
+
| {
|
|
14
|
+
readonly sequence: string;
|
|
15
|
+
readonly nextIndex: number;
|
|
16
|
+
}
|
|
17
|
+
| "pending"
|
|
18
|
+
| undefined;
|
|
19
|
+
|
|
20
|
+
const isCsiParameterByte = (byte: number): boolean => {
|
|
21
|
+
return byte >= 0x30 && byte <= 0x3f;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isCsiIntermediateByte = (byte: number): boolean => {
|
|
25
|
+
return byte >= 0x20 && byte <= 0x2f;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const isCsiFinalByte = (byte: number): boolean => {
|
|
29
|
+
return byte >= 0x40 && byte <= 0x7e;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const parseCsiSequence = (
|
|
33
|
+
input: string,
|
|
34
|
+
startIndex: number,
|
|
35
|
+
prefixLength: number,
|
|
36
|
+
): ParsedSequence => {
|
|
37
|
+
const csiPayloadStart = startIndex + prefixLength + 1;
|
|
38
|
+
let index = csiPayloadStart;
|
|
39
|
+
for (; index < input.length; index++) {
|
|
40
|
+
const byte = input.codePointAt(index);
|
|
41
|
+
if (byte === undefined) {
|
|
42
|
+
return "pending";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (isCsiParameterByte(byte) || isCsiIntermediateByte(byte)) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Preserve legacy terminal function-key sequences like ESC[[A and ESC[[5~.
|
|
50
|
+
if (byte === 0x5b && index === csiPayloadStart) {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (isCsiFinalByte(byte)) {
|
|
55
|
+
return {
|
|
56
|
+
sequence: input.slice(startIndex, index + 1),
|
|
57
|
+
nextIndex: index + 1,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return "pending";
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const parseSs3Sequence = (
|
|
68
|
+
input: string,
|
|
69
|
+
startIndex: number,
|
|
70
|
+
prefixLength: number,
|
|
71
|
+
): ParsedSequence => {
|
|
72
|
+
const nextIndex = startIndex + prefixLength + 2;
|
|
73
|
+
if (nextIndex > input.length) {
|
|
74
|
+
return "pending";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const finalByte = input.codePointAt(nextIndex - 1);
|
|
78
|
+
if (finalByte === undefined || !isCsiFinalByte(finalByte)) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
sequence: input.slice(startIndex, nextIndex),
|
|
84
|
+
nextIndex,
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const parseControlSequence = (
|
|
89
|
+
input: string,
|
|
90
|
+
startIndex: number,
|
|
91
|
+
prefixLength: number,
|
|
92
|
+
): ParsedSequence => {
|
|
93
|
+
const sequenceType = input[startIndex + prefixLength];
|
|
94
|
+
if (sequenceType === undefined) {
|
|
95
|
+
return "pending";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (sequenceType === "[") {
|
|
99
|
+
return parseCsiSequence(input, startIndex, prefixLength);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (sequenceType === "O") {
|
|
103
|
+
return parseSs3Sequence(input, startIndex, prefixLength);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const parseEscapedCodePoint = (
|
|
110
|
+
input: string,
|
|
111
|
+
escapeIndex: number,
|
|
112
|
+
): {
|
|
113
|
+
readonly sequence: string;
|
|
114
|
+
readonly nextIndex: number;
|
|
115
|
+
} => {
|
|
116
|
+
const nextCodePoint = input.codePointAt(escapeIndex + 1);
|
|
117
|
+
const nextCodePointLength = nextCodePoint !== undefined && nextCodePoint > 0xff_ff ? 2 : 1;
|
|
118
|
+
const nextIndex = escapeIndex + 1 + nextCodePointLength;
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
sequence: input.slice(escapeIndex, nextIndex),
|
|
122
|
+
nextIndex,
|
|
123
|
+
};
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
type ParsedEscapeSequence =
|
|
127
|
+
| {
|
|
128
|
+
readonly sequence: string;
|
|
129
|
+
readonly nextIndex: number;
|
|
130
|
+
}
|
|
131
|
+
| "pending";
|
|
132
|
+
|
|
133
|
+
const parseEscapeSequence = (input: string, escapeIndex: number): ParsedEscapeSequence => {
|
|
134
|
+
if (escapeIndex === input.length - 1) {
|
|
135
|
+
return "pending";
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const next = input[escapeIndex + 1]!;
|
|
139
|
+
if (next === escape) {
|
|
140
|
+
if (escapeIndex + 2 >= input.length) {
|
|
141
|
+
return "pending";
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const doubleEscapeSequence = parseControlSequence(input, escapeIndex, 2);
|
|
145
|
+
if (doubleEscapeSequence === "pending") {
|
|
146
|
+
return "pending";
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (doubleEscapeSequence) {
|
|
150
|
+
return doubleEscapeSequence;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
sequence: input.slice(escapeIndex, escapeIndex + 2),
|
|
155
|
+
nextIndex: escapeIndex + 2,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const controlSequence = parseControlSequence(input, escapeIndex, 1);
|
|
160
|
+
if (controlSequence === "pending") {
|
|
161
|
+
return "pending";
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (controlSequence) {
|
|
165
|
+
return controlSequence;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return parseEscapedCodePoint(input, escapeIndex);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
Split a chunk of non-escape text so that backspace bytes (`0x7F` and `0x08`) become individual events. When a user holds the backspace key, the terminal sends repeated bytes in a single stdin chunk. Without splitting, `parseKeypress` receives the multi-byte string and fails to recognize it as a key event, corrupting the input state.
|
|
173
|
+
|
|
174
|
+
Other control characters like `\r` and `\t` are NOT split because they can legitimately appear inside pasted text.
|
|
175
|
+
*/
|
|
176
|
+
const splitBackspaceBytes = (text: string, events: InputEvent[]): void => {
|
|
177
|
+
let textSegmentStart = 0;
|
|
178
|
+
|
|
179
|
+
for (let index = 0; index < text.length; index++) {
|
|
180
|
+
const character = text[index]!;
|
|
181
|
+
if (character === "\u007F" || character === "\u0008") {
|
|
182
|
+
if (index > textSegmentStart) {
|
|
183
|
+
events.push(text.slice(textSegmentStart, index));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
events.push(character);
|
|
187
|
+
textSegmentStart = index + 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (textSegmentStart < text.length) {
|
|
192
|
+
events.push(text.slice(textSegmentStart));
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const parseKeypresses = (input: string): ParsedInput => {
|
|
197
|
+
const events: InputEvent[] = [];
|
|
198
|
+
let index = 0;
|
|
199
|
+
const pendingFrom = (pendingStartIndex: number): ParsedInput => ({
|
|
200
|
+
events,
|
|
201
|
+
pending: input.slice(pendingStartIndex),
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
while (index < input.length) {
|
|
205
|
+
const escapeIndex = input.indexOf(escape, index);
|
|
206
|
+
if (escapeIndex === -1) {
|
|
207
|
+
splitBackspaceBytes(input.slice(index), events);
|
|
208
|
+
return {
|
|
209
|
+
events,
|
|
210
|
+
pending: "",
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (escapeIndex > index) {
|
|
215
|
+
splitBackspaceBytes(input.slice(index, escapeIndex), events);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const parsedEscapeSequence = parseEscapeSequence(input, escapeIndex);
|
|
219
|
+
if (parsedEscapeSequence === "pending") {
|
|
220
|
+
return pendingFrom(escapeIndex);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (parsedEscapeSequence.sequence === pasteStart) {
|
|
224
|
+
const afterStart = parsedEscapeSequence.nextIndex;
|
|
225
|
+
const endIndex = input.indexOf(pasteEnd, afterStart);
|
|
226
|
+
if (endIndex === -1) {
|
|
227
|
+
return pendingFrom(escapeIndex);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
events.push({ paste: input.slice(afterStart, endIndex) });
|
|
231
|
+
index = endIndex + pasteEnd.length;
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
events.push(parsedEscapeSequence.sequence);
|
|
236
|
+
index = parsedEscapeSequence.nextIndex;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
events,
|
|
241
|
+
pending: "",
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export type InputParser = {
|
|
246
|
+
push: (chunk: string) => InputEvent[];
|
|
247
|
+
hasPendingEscape: () => boolean;
|
|
248
|
+
flushPendingEscape: () => string | undefined;
|
|
249
|
+
reset: () => void;
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
export const createInputParser = (): InputParser => {
|
|
253
|
+
let pending = "";
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
push(chunk) {
|
|
257
|
+
const parsedInput = parseKeypresses(pending + chunk);
|
|
258
|
+
pending = parsedInput.pending;
|
|
259
|
+
return parsedInput.events;
|
|
260
|
+
},
|
|
261
|
+
hasPendingEscape() {
|
|
262
|
+
// Don't trigger the escape flush timer while assembling a paste start
|
|
263
|
+
// marker (`\u001B[200` and then `~`) or while waiting for paste end.
|
|
264
|
+
return (
|
|
265
|
+
pending.startsWith(escape) &&
|
|
266
|
+
!pending.startsWith(pasteStart) &&
|
|
267
|
+
pending !== pasteStart.slice(0, -1)
|
|
268
|
+
);
|
|
269
|
+
},
|
|
270
|
+
flushPendingEscape() {
|
|
271
|
+
if (!pending.startsWith(escape)) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const pendingEscape = pending;
|
|
276
|
+
pending = "";
|
|
277
|
+
return pendingEscape;
|
|
278
|
+
},
|
|
279
|
+
reset() {
|
|
280
|
+
pending = "";
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
};
|
package/src/instances.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Store all instances of Ink (instance.js) to ensure that consecutive render() calls
|
|
2
|
+
// use the same instance of Ink and don't create a new one
|
|
3
|
+
//
|
|
4
|
+
// This map has to be stored in a separate file, because render.js creates instances,
|
|
5
|
+
// but instance.js should delete itself from the map on unmount
|
|
6
|
+
|
|
7
|
+
import type { Ink } from "./ink.tsx";
|
|
8
|
+
|
|
9
|
+
export const instances = new WeakMap<NodeJS.WritableStream, Ink>();
|
package/src/is-in-ci.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Derived from `is-in-ci` (MIT, Sindre Sorhus).
|
|
2
|
+
import process from "node:process";
|
|
3
|
+
|
|
4
|
+
const check = (key: string): boolean =>
|
|
5
|
+
key in process.env && process.env[key] !== "0" && process.env[key] !== "false";
|
|
6
|
+
|
|
7
|
+
export const isInCi = check("CI") || check("CONTINUOUS_INTEGRATION");
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Kitty keyboard protocol flags.
|
|
2
|
+
// @see https://sw.kovidgoyal.net/kitty/keyboard-protocol/
|
|
3
|
+
export const kittyFlags = {
|
|
4
|
+
disambiguateEscapeCodes: 1,
|
|
5
|
+
reportEventTypes: 2,
|
|
6
|
+
reportAlternateKeys: 4,
|
|
7
|
+
reportAllKeysAsEscapeCodes: 8,
|
|
8
|
+
reportAssociatedText: 16,
|
|
9
|
+
} as const;
|
|
10
|
+
|
|
11
|
+
// Valid flag names for the kitty keyboard protocol.
|
|
12
|
+
export type KittyFlagName = keyof typeof kittyFlags;
|
|
13
|
+
|
|
14
|
+
// Converts an array of flag names to the corresponding bitmask value.
|
|
15
|
+
export function resolveFlags(flags: KittyFlagName[]): number {
|
|
16
|
+
let result = 0;
|
|
17
|
+
for (const flag of flags) {
|
|
18
|
+
// eslint-disable-next-line no-bitwise
|
|
19
|
+
result |= kittyFlags[flag];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return result;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Kitty keyboard modifier bits.
|
|
26
|
+
// These are used in the modifier parameter of CSI u sequences.
|
|
27
|
+
// Note: The actual modifier value is (modifiers - 1) as per the protocol.
|
|
28
|
+
export const kittyModifiers = {
|
|
29
|
+
shift: 1,
|
|
30
|
+
alt: 2,
|
|
31
|
+
ctrl: 4,
|
|
32
|
+
super: 8,
|
|
33
|
+
hyper: 16,
|
|
34
|
+
meta: 32,
|
|
35
|
+
capsLock: 64,
|
|
36
|
+
numLock: 128,
|
|
37
|
+
} as const;
|
|
38
|
+
|
|
39
|
+
// Options for configuring kitty keyboard protocol.
|
|
40
|
+
export type KittyKeyboardOptions = {
|
|
41
|
+
// Mode for kitty keyboard protocol support.
|
|
42
|
+
// - 'auto': Attempt to detect terminal support (default)
|
|
43
|
+
// - 'enabled': Force enable the protocol
|
|
44
|
+
// - 'disabled': Never enable the protocol
|
|
45
|
+
mode?: "auto" | "enabled" | "disabled";
|
|
46
|
+
|
|
47
|
+
// Protocol flags to request from the terminal.
|
|
48
|
+
// Pass an array of flag name strings.
|
|
49
|
+
//
|
|
50
|
+
// Available flags:
|
|
51
|
+
// - 'disambiguateEscapeCodes' - Disambiguate escape codes (default)
|
|
52
|
+
// - 'reportEventTypes' - Report key press, repeat, and release events
|
|
53
|
+
// - 'reportAlternateKeys' - Report alternate key encodings
|
|
54
|
+
// - 'reportAllKeysAsEscapeCodes' - Report all keys as escape codes
|
|
55
|
+
// - 'reportAssociatedText' - Report associated text with key events
|
|
56
|
+
flags?: KittyFlagName[];
|
|
57
|
+
};
|