@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.
Files changed (138) hide show
  1. package/README.md +21 -9
  2. package/THIRD_PARTY_NOTICES.md +39 -1
  3. package/dist/Text-BobFKi74.d.ts +452 -0
  4. package/dist/ansi.d.ts +122 -131
  5. package/dist/ansi.js +86 -6
  6. package/dist/capabilities.d.ts +5 -0
  7. package/dist/capabilities.js +3 -0
  8. package/dist/cell-_ZVhbfl0.js +44 -0
  9. package/dist/color-CkbalRqK.js +2 -0
  10. package/dist/color-policy-BMzMwV7Q.d.ts +22 -0
  11. package/dist/color-policy-SVj1pYTA.js +560 -0
  12. package/dist/color-profile-DHhQHY55.js +36 -0
  13. package/dist/color-profile-u0Nhe9Nv.d.ts +97 -0
  14. package/dist/color.d.ts +21 -0
  15. package/dist/color.js +3 -0
  16. package/dist/cursor-position-D2LAkRG0.d.ts +7 -0
  17. package/dist/detect-Bh4yGP6w.d.ts +186 -0
  18. package/dist/detect-BuTXtY6e.js +373 -0
  19. package/dist/env-YVw64yZS.js +9 -0
  20. package/dist/escapes-CB_6CWOE.d.ts +72 -0
  21. package/dist/geometry-BxXOzJgo.d.ts +11 -0
  22. package/dist/index-DZ88EXJv.d.ts +21 -0
  23. package/dist/index.d.ts +143 -498
  24. package/dist/index.js +1026 -2244
  25. package/dist/osc-CCH7xDoS.js +71 -0
  26. package/dist/osc-Cn0fw77g.d.ts +23 -0
  27. package/dist/paint-C19minOS.d.ts +81 -0
  28. package/dist/query-vaIeGOkH.d.ts +152 -0
  29. package/dist/router.d.ts +392 -0
  30. package/dist/router.js +709 -0
  31. package/dist/sample-Cqw1bjUL.js +445 -0
  32. package/dist/screen-BOSLQ8fF.d.ts +49 -0
  33. package/dist/screen-CiPytswf.js +342 -0
  34. package/dist/screen.d.ts +5 -0
  35. package/dist/screen.js +5 -0
  36. package/dist/semantic-text-style-DIMzC7xt.js +91 -0
  37. package/dist/serialize-BTkAZgw1.js +79 -0
  38. package/dist/session-aZr9O8h3.js +665 -0
  39. package/dist/sgr-BhwaWAJB.js +246 -0
  40. package/dist/store-CgrG9K4y.d.ts +72 -0
  41. package/dist/string-width-CijQwpIk.js +69 -0
  42. package/dist/strip-BvU4toXG.js +6 -0
  43. package/dist/terminal.d.ts +118 -0
  44. package/dist/terminal.js +2 -0
  45. package/dist/tokenize-AjqbvtiT.js +1242 -0
  46. package/dist/tokenize-Dx1y_l5H.d.ts +57 -0
  47. package/dist/truncate-D31fhU6i.js +562 -0
  48. package/dist/use-focus-BzqAJi0n.js +1337 -0
  49. package/package.json +41 -9
  50. package/src/ansi/chalk.ts +5 -3
  51. package/src/ansi/escapes.ts +14 -0
  52. package/src/ansi/graphemes.ts +8 -0
  53. package/src/ansi/hyperlink.ts +44 -0
  54. package/src/ansi/index.ts +3 -1
  55. package/src/ansi/osc.ts +77 -0
  56. package/src/ansi/tokenize.ts +3 -4
  57. package/src/capabilities/color-policy.ts +34 -0
  58. package/src/capabilities/detect.ts +594 -0
  59. package/src/capabilities/index.ts +37 -0
  60. package/src/capabilities/query.ts +657 -0
  61. package/src/capabilities/store.ts +379 -0
  62. package/src/color/index.ts +3 -0
  63. package/src/color/paint.ts +169 -0
  64. package/src/color/palette.ts +48 -0
  65. package/src/color/sample.ts +323 -0
  66. package/src/color.ts +1 -0
  67. package/src/components/AnsiText.tsx +42 -0
  68. package/src/components/App.tsx +98 -10
  69. package/src/components/BackgroundContext.ts +2 -3
  70. package/src/components/Box.tsx +0 -8
  71. package/src/components/CursorContext.ts +1 -1
  72. package/src/components/Hyperlink.tsx +56 -0
  73. package/src/components/TerminalOscContext.ts +25 -0
  74. package/src/components/Text.tsx +22 -45
  75. package/src/components/Transform.tsx +1 -1
  76. package/src/dom.ts +11 -2
  77. package/src/global.d.ts +3 -0
  78. package/src/hooks/use-capabilities.ts +73 -0
  79. package/src/hooks/use-cursor.ts +2 -2
  80. package/src/hooks/use-terminal-osc.ts +59 -0
  81. package/src/index.ts +45 -1
  82. package/src/ink.tsx +213 -153
  83. package/src/{render-node-to-output.ts → paint-tree.ts} +75 -48
  84. package/src/reconciler.ts +24 -3
  85. package/src/render-background.ts +36 -15
  86. package/src/render-border.ts +94 -61
  87. package/src/render-frame.ts +83 -0
  88. package/src/render-to-string.ts +21 -6
  89. package/src/render.ts +15 -6
  90. package/src/router/components.tsx +343 -0
  91. package/src/router/context.ts +41 -0
  92. package/src/router/history.ts +194 -0
  93. package/src/router/hooks.tsx +391 -0
  94. package/src/router/index.ts +34 -0
  95. package/src/router/matcher.ts +571 -0
  96. package/src/screen/ansi.ts +184 -0
  97. package/src/screen/canvas.ts +160 -0
  98. package/src/screen/cell.ts +138 -0
  99. package/src/screen/color-profile.ts +47 -0
  100. package/src/screen/geometry.ts +9 -0
  101. package/src/screen/index.ts +6 -0
  102. package/src/screen/screen.ts +305 -0
  103. package/src/screen/serialize.ts +129 -0
  104. package/src/screen.ts +1 -0
  105. package/src/semantic-text-style.ts +118 -0
  106. package/src/squash-text-nodes.ts +2 -5
  107. package/src/structured-text.ts +325 -0
  108. package/src/styles.ts +19 -14
  109. package/src/terminal/index.ts +2 -0
  110. package/src/terminal/inline-presenter.ts +120 -0
  111. package/src/terminal/input.ts +86 -0
  112. package/src/terminal/render-scheduler.ts +37 -0
  113. package/src/terminal/screen-presenter.ts +188 -0
  114. package/src/terminal/session.ts +407 -0
  115. package/src/terminal.ts +1 -0
  116. package/src/testing/browser.ts +588 -0
  117. package/src/testing/emulators.ts +205 -0
  118. package/src/testing/explorer-app/index.html +12 -0
  119. package/src/testing/explorer-app/main.ts +381 -0
  120. package/src/testing/explorer-app/style.css +194 -0
  121. package/src/testing/explorer-app/tsconfig.json +15 -0
  122. package/src/testing/explorer-app/vite-env.d.ts +1 -0
  123. package/src/testing/index.ts +26 -0
  124. package/src/testing/keys.ts +56 -0
  125. package/src/testing/live.ts +85 -0
  126. package/src/testing/matchers.ts +70 -0
  127. package/src/testing/public.ts +94 -0
  128. package/src/testing/terminal.ts +349 -0
  129. package/src/testing/vitest.ts +157 -0
  130. package/src/transform-adapter.ts +14 -0
  131. package/src/wrap-text.ts +4 -0
  132. package/dist/sgr-CMfEpjSk.d.ts +0 -91
  133. package/dist/truncate-Cr6xVFMa.js +0 -2330
  134. package/src/ansi/supports-color.ts +0 -207
  135. package/src/colorize.ts +0 -60
  136. package/src/log-update.ts +0 -370
  137. package/src/output.ts +0 -308
  138. package/src/renderer.ts +0 -73
@@ -0,0 +1,21 @@
1
+ import { c as Color, d as RgbColor } from "./color-profile-u0Nhe9Nv.js";
2
+ import { _ as perimeterGradient, a as LinearGradient, c as PaintContext, d as adaptive, f as ansi, g as perProfile, h as named, i as InterpolationSpace, l as PerimeterGradient, m as linearGradient, n as ColorInput, o as NamedColor, p as ansi256, r as GradientStop, s as Paint, t as AdaptiveColor, u as ProfileColor, v as rgb } from "./paint-C19minOS.js";
3
+ import { n as Rect } from "./geometry-BxXOzJgo.js";
4
+ //#region src/color/palette.d.ts
5
+ declare const canonicalAnsiPalette: readonly RgbColor[];
6
+ declare function colorToRgb(color: Color, palette?: readonly {
7
+ r: number;
8
+ g: number;
9
+ b: number;
10
+ }[]): RgbColor;
11
+ //#endregion
12
+ //#region src/color/sample.d.ts
13
+ declare function samplePaint(paint: Paint, x: number, y: number, bounds: Rect, context?: PaintContext): Color | undefined;
14
+ declare function blend(source: Color, destination: Color, palette?: PaintContext["palette"]): Color;
15
+ /** Progressively moves a color toward white in perceptual OKLab space. */
16
+ declare function lighten(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor;
17
+ /** Progressively moves a color toward black in perceptual OKLab space. */
18
+ declare function darken(color: Color, amount: number, palette?: PaintContext["palette"]): RgbColor;
19
+ declare function interpolateColor(from: Color, to: Color, amount: number, space?: InterpolationSpace, palette?: PaintContext["palette"]): RgbColor;
20
+ //#endregion
21
+ export { AdaptiveColor, ColorInput, GradientStop, InterpolationSpace, LinearGradient, NamedColor, Paint, PaintContext, PerimeterGradient, ProfileColor, adaptive, ansi, ansi256, blend, canonicalAnsiPalette, colorToRgb, darken, interpolateColor, lighten, linearGradient, named, perProfile, perimeterGradient, rgb, samplePaint };
package/dist/color.js ADDED
@@ -0,0 +1,3 @@
1
+ import { a as samplePaint, c as adaptive, d as linearGradient, f as named, h as rgb, i as lighten, l as ansi, m as perimeterGradient, n as darken, o as canonicalAnsiPalette, p as perProfile, r as interpolateColor, s as colorToRgb, t as blend, u as ansi256 } from "./sample-Cqw1bjUL.js";
2
+ import "./color-CkbalRqK.js";
3
+ export { adaptive, ansi, ansi256, blend, canonicalAnsiPalette, colorToRgb, darken, interpolateColor, lighten, linearGradient, named, perProfile, perimeterGradient, rgb, samplePaint };
@@ -0,0 +1,7 @@
1
+ //#region src/cursor-position.d.ts
2
+ type CursorPosition = {
3
+ x: number;
4
+ y: number;
5
+ };
6
+ //#endregion
7
+ export { CursorPosition as t };
@@ -0,0 +1,186 @@
1
+ //#region src/capabilities/detect.d.ts
2
+ /**
3
+ An RGB color with 8-bit channels, as reported by the terminal.
4
+ */
5
+ type RgbColor = {
6
+ r: number;
7
+ g: number;
8
+ b: number;
9
+ };
10
+ type TerminalAppearance = "dark" | "light";
11
+ type Multiplexer = "tmux" | "screen" | "zellij";
12
+ /**
13
+ Color support level: 0 = none, 1 = 16 colors, 2 = 256 colors, 3 = truecolor.
14
+ */
15
+ type ColorSupportLevel = 0 | 1 | 2 | 3;
16
+ /**
17
+ The chalk-compatible color support shape.
18
+ */
19
+ type ColorSupport = {
20
+ readonly level: ColorSupportLevel;
21
+ readonly hasBasic: boolean;
22
+ readonly has256: boolean;
23
+ readonly has16m: boolean;
24
+ };
25
+ type ColorInfo = ColorSupport | false;
26
+ type TerminalIdentity = {
27
+ /**
28
+ Normalized terminal name (`"kitty"`, `"iterm"`, `"wezterm"`, …), or
29
+ `undefined` when unknown. `queryTerminal` can refine this with the
30
+ terminal's own XTVERSION answer.
31
+ */
32
+ name: string | undefined;
33
+ /**
34
+ The terminal's version, when the environment reports one.
35
+ */
36
+ version: string | undefined;
37
+ /**
38
+ The raw `TERM` environment variable.
39
+ */
40
+ term: string | undefined;
41
+ /**
42
+ The multiplexer the app is running under, if any. Note that inside a
43
+ multiplexer, capabilities reflect the multiplexer — not the outer terminal.
44
+ */
45
+ multiplexer: Multiplexer | undefined;
46
+ };
47
+ type PixelGeometry = {
48
+ /**
49
+ Text area size in pixels (XTWINOPS 14).
50
+ */
51
+ textArea: {
52
+ width: number;
53
+ height: number;
54
+ } | undefined;
55
+ /**
56
+ Size of a single character cell in pixels (XTWINOPS 16).
57
+ */
58
+ cell: {
59
+ width: number;
60
+ height: number;
61
+ } | undefined;
62
+ };
63
+ type Capabilities = {
64
+ /**
65
+ Current terminal dimensions in cells, plus pixel geometry once the
66
+ terminal has answered the query.
67
+ */
68
+ size: {
69
+ columns: number;
70
+ rows: number;
71
+ pixels: PixelGeometry | undefined;
72
+ };
73
+ platform: NodeJS.Platform;
74
+ /**
75
+ Running under a CI provider.
76
+ */
77
+ ci: boolean;
78
+ /**
79
+ Running over an SSH connection.
80
+ */
81
+ ssh: boolean;
82
+ screenReader: boolean;
83
+ /**
84
+ Same detection `render()` uses: stdout is a TTY and not CI.
85
+ */
86
+ interactive: boolean;
87
+ /**
88
+ Whether the terminal window has focus. Requires focus events (mode 1004),
89
+ which the capabilities store enables automatically while it has
90
+ subscribers; `undefined` until the first focus report arrives.
91
+ */
92
+ focused: boolean | undefined;
93
+ terminal: TerminalIdentity;
94
+ color: {
95
+ level: ColorSupportLevel;
96
+ /**
97
+ The same fact as bits per color: 1, 4, 8, or 24.
98
+ */
99
+ depth: 1 | 4 | 8 | 24;
100
+ trueColor: boolean;
101
+ };
102
+ theme: {
103
+ /**
104
+ The terminal's own appearance. After `queryTerminal` this is derived
105
+ from the actual background color's luminance (a dark terminal theme on
106
+ a light OS stays `"dark"`); before that it's a `COLORFGBG` guess.
107
+ */
108
+ appearance: TerminalAppearance | undefined;
109
+ /**
110
+ The operating system's color preference, from the color scheme report.
111
+ Independent of the terminal's own theme — only available after
112
+ `queryTerminal` on terminals that support the report.
113
+ */
114
+ systemAppearance: TerminalAppearance | undefined;
115
+ /**
116
+ The user's configured foreground/background/cursor colors and 16-color
117
+ palette. Only available after `queryTerminal`.
118
+ */
119
+ foreground: RgbColor | undefined;
120
+ background: RgbColor | undefined;
121
+ cursor: RgbColor | undefined;
122
+ palette: RgbColor[] | undefined;
123
+ };
124
+ /**
125
+ Feature support. Fields typed `boolean | undefined` are only knowable by
126
+ asking the terminal — they stay `undefined` until `queryTerminal` has
127
+ answered (see `TerminalQueryResult` for what each means).
128
+ */
129
+ supports: {
130
+ color: boolean;
131
+ hyperlinks: boolean;
132
+ unicode: boolean;
133
+ alternateScreen: boolean;
134
+ kittyKeyboard: boolean | undefined;
135
+ kittyGraphics: boolean | undefined;
136
+ sixel: boolean | undefined;
137
+ focusEvents: boolean | undefined;
138
+ sgrMouse: boolean | undefined;
139
+ sgrPixelMouse: boolean | undefined;
140
+ bracketedPaste: boolean | undefined;
141
+ synchronizedOutput: boolean | undefined;
142
+ graphemeClustering: boolean | undefined;
143
+ colorSchemeUpdates: boolean | undefined;
144
+ inBandResize: boolean | undefined;
145
+ };
146
+ };
147
+ declare function detectTerminal(): TerminalIdentity;
148
+ type DetectStream = {
149
+ isTTY?: boolean;
150
+ };
151
+ /**
152
+ Detects the color support level for a stream from the environment. Purely
153
+ env-derived — the terminal query can upgrade this to truecolor when the
154
+ terminal confirms it via XTGETTCAP.
155
+ */
156
+ declare function detectColorLevel(stream?: DetectStream): ColorSupportLevel;
157
+ /**
158
+ The color level in chalk's `ColorInfo` shape.
159
+ */
160
+ declare function createSupportsColor(stream?: DetectStream): ColorInfo;
161
+ /**
162
+ Detects OSC 8 hyperlink support for a stream from the environment.
163
+ */
164
+ declare function detectHyperlinkSupport(stream?: DetectStream): boolean;
165
+ /**
166
+ Detects whether the terminal renders unicode reliably.
167
+ */
168
+ declare function detectUnicodeSupport(): boolean;
169
+ type CapabilityStdout = DetectStream & {
170
+ columns?: number;
171
+ rows?: number;
172
+ };
173
+ type DetectOptions = {
174
+ stdout?: CapabilityStdout;
175
+ };
176
+ /**
177
+ Takes a snapshot of everything knowable about the terminal from streams and
178
+ environment variables. The environment-derived parts are computed once per
179
+ stream and cached; size and theme are read fresh on every call. Fields that
180
+ require asking the terminal itself start as `undefined` — run `queryTerminal`
181
+ and merge with `applyTerminalQuery` to fill them in, or use the
182
+ `useCapabilities` hook which does both.
183
+ */
184
+ declare function detectCapabilities({ stdout }?: DetectOptions): Capabilities;
185
+ //#endregion
186
+ export { Multiplexer as a, TerminalAppearance as c, detectCapabilities as d, detectColorLevel as f, detectUnicodeSupport as h, ColorSupportLevel as i, TerminalIdentity as l, detectTerminal as m, ColorInfo as n, PixelGeometry as o, detectHyperlinkSupport as p, ColorSupport as r, RgbColor as s, Capabilities as t, createSupportsColor as u };
@@ -0,0 +1,373 @@
1
+ import { n as isMacos, o as isWindows, r as isScreenReader, t as isInCi } from "./env-YVw64yZS.js";
2
+ import { constants, openSync } from "node:fs";
3
+ import { WriteStream } from "node:tty";
4
+ //#region src/signal-exit.ts
5
+ const signals = isWindows ? [
6
+ "SIGHUP",
7
+ "SIGINT",
8
+ "SIGTERM",
9
+ "SIGBREAK"
10
+ ] : [
11
+ "SIGHUP",
12
+ "SIGINT",
13
+ "SIGTERM",
14
+ "SIGQUIT",
15
+ "SIGUSR2"
16
+ ];
17
+ const registrations = /* @__PURE__ */ new Set();
18
+ const signalListeners = /* @__PURE__ */ new Map();
19
+ let loaded = false;
20
+ let emitted = false;
21
+ const emitExit = (code, signal) => {
22
+ if (emitted) return;
23
+ emitted = true;
24
+ const ordered = [...registrations].toSorted((a, b) => Number(a.alwaysLast) - Number(b.alwaysLast));
25
+ for (const registration of ordered) registration.handler(code, signal);
26
+ };
27
+ const onExitEvent = (code) => {
28
+ emitExit(code, null);
29
+ };
30
+ const unload = () => {
31
+ if (!loaded) return;
32
+ loaded = false;
33
+ process.off("exit", onExitEvent);
34
+ for (const [signal, listener] of signalListeners) process.off(signal, listener);
35
+ signalListeners.clear();
36
+ };
37
+ const load = () => {
38
+ if (loaded) return;
39
+ loaded = true;
40
+ process.on("exit", onExitEvent);
41
+ for (const signal of signals) {
42
+ const listener = () => {
43
+ if (process.listenerCount(signal) === 1) {
44
+ unload();
45
+ emitExit(null, signal);
46
+ process.kill(process.pid, signal);
47
+ }
48
+ };
49
+ try {
50
+ process.on(signal, listener);
51
+ signalListeners.set(signal, listener);
52
+ } catch {}
53
+ }
54
+ };
55
+ const signalExit = (handler, options = {}) => {
56
+ const registration = {
57
+ handler,
58
+ alwaysLast: options.alwaysLast ?? false
59
+ };
60
+ registrations.add(registration);
61
+ load();
62
+ return () => {
63
+ registrations.delete(registration);
64
+ if (registrations.size === 0) unload();
65
+ };
66
+ };
67
+ //#endregion
68
+ //#region src/terminal-size.ts
69
+ const create = (columns, rows) => ({
70
+ columns: Number.parseInt(String(columns), 10),
71
+ rows: Number.parseInt(String(rows), 10)
72
+ });
73
+ const devTty = () => {
74
+ try {
75
+ const { O_EVTONLY: evtOnly } = constants;
76
+ const flags = isMacos && evtOnly !== void 0 ? evtOnly | constants.O_NONBLOCK : constants.O_NONBLOCK;
77
+ const { columns, rows } = new WriteStream(openSync("/dev/tty", flags));
78
+ if (columns && rows) return {
79
+ columns,
80
+ rows
81
+ };
82
+ } catch {}
83
+ };
84
+ const terminalSize = () => {
85
+ const { env, stdout, stderr } = process;
86
+ if (stdout?.columns && stdout?.rows) return create(stdout.columns, stdout.rows);
87
+ if (stderr?.columns && stderr?.rows) return create(stderr.columns, stderr.rows);
88
+ if (env["COLUMNS"] && env["LINES"]) return create(env["COLUMNS"], env["LINES"]);
89
+ return devTty() ?? {
90
+ columns: 80,
91
+ rows: 24
92
+ };
93
+ };
94
+ //#endregion
95
+ //#region src/capabilities/detect.ts
96
+ const { env } = process;
97
+ const terminalKnowledge = {
98
+ iterm: {
99
+ trueColor: true,
100
+ hyperlinks: { since: [3, 1] }
101
+ },
102
+ "apple-terminal": { colorLevel: 2 },
103
+ wezterm: {
104
+ trueColor: true,
105
+ hyperlinks: true
106
+ },
107
+ vscode: {
108
+ trueColor: true,
109
+ hyperlinks: { since: [1, 72] }
110
+ },
111
+ ghostty: {
112
+ trueColor: true,
113
+ hyperlinks: true
114
+ },
115
+ kitty: {
116
+ trueColor: true,
117
+ hyperlinks: true
118
+ },
119
+ alacritty: {
120
+ trueColor: true,
121
+ hyperlinks: true
122
+ },
123
+ foot: {
124
+ trueColor: true,
125
+ hyperlinks: true
126
+ },
127
+ contour: {
128
+ trueColor: true,
129
+ hyperlinks: true
130
+ },
131
+ "windows-terminal": {
132
+ trueColor: true,
133
+ hyperlinks: true
134
+ },
135
+ konsole: {
136
+ trueColor: true,
137
+ hyperlinks: true
138
+ },
139
+ vte: {
140
+ trueColor: true,
141
+ hyperlinks: { since: [0, 50] }
142
+ },
143
+ hyper: { trueColor: true },
144
+ tabby: {
145
+ trueColor: true,
146
+ hyperlinks: true
147
+ },
148
+ rio: {
149
+ trueColor: true,
150
+ hyperlinks: true
151
+ }
152
+ };
153
+ const termProgramNames = {
154
+ "iTerm.app": "iterm",
155
+ Apple_Terminal: "apple-terminal",
156
+ WezTerm: "wezterm",
157
+ vscode: "vscode",
158
+ ghostty: "ghostty",
159
+ Hyper: "hyper",
160
+ Tabby: "tabby",
161
+ rio: "rio"
162
+ };
163
+ const termNames = {
164
+ "xterm-kitty": "kitty",
165
+ "xterm-ghostty": "ghostty",
166
+ alacritty: "alacritty",
167
+ wezterm: "wezterm",
168
+ foot: "foot",
169
+ contour: "contour"
170
+ };
171
+ const parseVteVersion = (raw) => {
172
+ const numeric = Number.parseInt(raw, 10);
173
+ if (Number.isNaN(numeric)) return;
174
+ return `${Math.floor(numeric / 1e4)}.${Math.floor(numeric / 100) % 100}.${numeric % 100}`;
175
+ };
176
+ const versionAtLeast = (version, [major, minor]) => {
177
+ if (!version) return false;
178
+ const [haveMajor = 0, haveMinor = 0] = version.split(".").map((part) => Number.parseInt(part, 10) || 0);
179
+ return haveMajor > major || haveMajor === major && haveMinor >= minor;
180
+ };
181
+ function detectTerminal() {
182
+ const term = env["TERM"];
183
+ let multiplexer;
184
+ if ("TMUX" in env || env["TERM_PROGRAM"] === "tmux") multiplexer = "tmux";
185
+ else if ("ZELLIJ" in env) multiplexer = "zellij";
186
+ else if (term?.startsWith("screen")) multiplexer = "screen";
187
+ let name;
188
+ let version;
189
+ const termProgram = env["TERM_PROGRAM"];
190
+ if (termProgram && termProgram !== "tmux" && termProgram in termProgramNames) {
191
+ name = termProgramNames[termProgram];
192
+ version = env["TERM_PROGRAM_VERSION"];
193
+ } else if (term && term in termNames) name = termNames[term];
194
+ else if ("WT_SESSION" in env) name = "windows-terminal";
195
+ else if ("KONSOLE_VERSION" in env) {
196
+ name = "konsole";
197
+ version = env["KONSOLE_VERSION"];
198
+ } else if ("VTE_VERSION" in env) {
199
+ name = "vte";
200
+ version = parseVteVersion(env["VTE_VERSION"]);
201
+ }
202
+ return {
203
+ name,
204
+ version,
205
+ term,
206
+ multiplexer
207
+ };
208
+ }
209
+ const knowledgeOf = (identity) => identity.name === void 0 ? void 0 : terminalKnowledge[identity.name];
210
+ const forcedColorLevel = () => {
211
+ const forced = env["FORCE_COLOR"];
212
+ if (forced === void 0) return;
213
+ if (forced === "true" || forced.length === 0) return 1;
214
+ if (forced === "false") return 0;
215
+ return Math.min(Math.max(Number.parseInt(forced, 10) || 0, 0), 3);
216
+ };
217
+ /**
218
+ Detects the color support level for a stream from the environment. Purely
219
+ env-derived — the terminal query can upgrade this to truecolor when the
220
+ terminal confirms it via XTGETTCAP.
221
+ */
222
+ function detectColorLevel(stream) {
223
+ const forced = forcedColorLevel();
224
+ if (forced === 0) return 0;
225
+ if (env["TF_BUILD"] && env["AGENT_NAME"]) return 1;
226
+ if (stream && !stream.isTTY && forced === void 0) return 0;
227
+ const minimum = forced ?? 0;
228
+ if (env["TERM"] === "dumb") return minimum;
229
+ if (isWindows) return 3;
230
+ if (env["CI"]) {
231
+ if ([
232
+ "GITHUB_ACTIONS",
233
+ "GITEA_ACTIONS",
234
+ "CIRCLECI"
235
+ ].some((key) => key in env)) return 3;
236
+ if ([
237
+ "TRAVIS",
238
+ "APPVEYOR",
239
+ "GITLAB_CI",
240
+ "BUILDKITE",
241
+ "DRONE"
242
+ ].some((key) => key in env) || env["CI_NAME"] === "codeship") return 1;
243
+ return minimum;
244
+ }
245
+ if (env["TEAMCITY_VERSION"]) return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env["TEAMCITY_VERSION"]) ? 1 : 0;
246
+ if (env["COLORTERM"] === "truecolor") return 3;
247
+ const knowledge = knowledgeOf(detectTerminal());
248
+ if (knowledge) {
249
+ if (knowledge.trueColor) return 3;
250
+ if (knowledge.colorLevel !== void 0) return knowledge.colorLevel;
251
+ }
252
+ if (/-256(color)?$/i.test(env["TERM"] ?? "")) return 2;
253
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env["TERM"] ?? "")) return 1;
254
+ if ("COLORTERM" in env) return 1;
255
+ return minimum;
256
+ }
257
+ /**
258
+ The color level in chalk's `ColorInfo` shape.
259
+ */
260
+ function createSupportsColor(stream) {
261
+ const level = detectColorLevel(stream);
262
+ if (level === 0) return false;
263
+ return {
264
+ level,
265
+ hasBasic: true,
266
+ has256: level >= 2,
267
+ has16m: level >= 3
268
+ };
269
+ }
270
+ /**
271
+ Detects OSC 8 hyperlink support for a stream from the environment.
272
+ */
273
+ function detectHyperlinkSupport(stream) {
274
+ if ("FORCE_HYPERLINK" in env) return !(env["FORCE_HYPERLINK"].length > 0 && Number.parseInt(env["FORCE_HYPERLINK"], 10) === 0);
275
+ if (detectColorLevel(stream) === 0) return false;
276
+ if (stream && !stream.isTTY) return false;
277
+ if (env["CI"] || env["TEAMCITY_VERSION"]) return false;
278
+ const identity = detectTerminal();
279
+ const hyperlinks = knowledgeOf(identity)?.hyperlinks;
280
+ if (hyperlinks === true) return true;
281
+ if (hyperlinks) return versionAtLeast(identity.version, hyperlinks.since);
282
+ return false;
283
+ }
284
+ /**
285
+ Detects whether the terminal renders unicode reliably.
286
+ */
287
+ function detectUnicodeSupport() {
288
+ if (process.platform !== "win32") return env["TERM"] !== "linux";
289
+ const { name } = detectTerminal();
290
+ return name === "windows-terminal" || name === "vscode" || name === "alacritty" || Boolean(env["TERMINUS_SUBLIME"]) || env["ConEmuTask"] === "{cmd::Cmder}" || env["TERM_PROGRAM"] === "Terminus-Sublime" || env["TERM"] === "xterm-256color" || env["TERMINAL_EMULATOR"] === "JetBrains-JediTerm";
291
+ }
292
+ const appearanceFromColorFgBg = () => {
293
+ const background = (env["COLORFGBG"]?.split(";"))?.at(-1);
294
+ if (!background || Number.isNaN(Number.parseInt(background, 10))) return;
295
+ return background === "7" || background === "15" ? "light" : "dark";
296
+ };
297
+ const colorDepths = {
298
+ 0: 1,
299
+ 1: 4,
300
+ 2: 8,
301
+ 3: 24
302
+ };
303
+ const staticCache = /* @__PURE__ */ new WeakMap();
304
+ const computeStatic = (stdout) => {
305
+ const level = detectColorLevel(stdout);
306
+ const interactive = !isInCi && Boolean(stdout.isTTY);
307
+ return {
308
+ platform: process.platform,
309
+ ci: isInCi,
310
+ ssh: "SSH_CONNECTION" in env || "SSH_CLIENT" in env || "SSH_TTY" in env,
311
+ screenReader: isScreenReader,
312
+ interactive,
313
+ terminal: detectTerminal(),
314
+ color: {
315
+ level,
316
+ depth: colorDepths[level],
317
+ trueColor: level === 3
318
+ },
319
+ supports: {
320
+ color: level > 0,
321
+ hyperlinks: detectHyperlinkSupport(stdout),
322
+ unicode: detectUnicodeSupport(),
323
+ alternateScreen: interactive && env["TERM"] !== "dumb",
324
+ kittyKeyboard: void 0,
325
+ kittyGraphics: void 0,
326
+ sixel: void 0,
327
+ focusEvents: void 0,
328
+ sgrMouse: void 0,
329
+ sgrPixelMouse: void 0,
330
+ bracketedPaste: void 0,
331
+ synchronizedOutput: void 0,
332
+ graphemeClustering: void 0,
333
+ colorSchemeUpdates: void 0,
334
+ inBandResize: void 0
335
+ }
336
+ };
337
+ };
338
+ /**
339
+ Takes a snapshot of everything knowable about the terminal from streams and
340
+ environment variables. The environment-derived parts are computed once per
341
+ stream and cached; size and theme are read fresh on every call. Fields that
342
+ require asking the terminal itself start as `undefined` — run `queryTerminal`
343
+ and merge with `applyTerminalQuery` to fill them in, or use the
344
+ `useCapabilities` hook which does both.
345
+ */
346
+ function detectCapabilities({ stdout = process.stdout } = {}) {
347
+ let staticParts = staticCache.get(stdout);
348
+ if (!staticParts) {
349
+ staticParts = computeStatic(stdout);
350
+ staticCache.set(stdout, staticParts);
351
+ }
352
+ return {
353
+ ...staticParts,
354
+ size: {
355
+ ...stdout.columns && stdout.rows ? {
356
+ columns: stdout.columns,
357
+ rows: stdout.rows
358
+ } : terminalSize(),
359
+ pixels: void 0
360
+ },
361
+ focused: void 0,
362
+ theme: {
363
+ appearance: appearanceFromColorFgBg(),
364
+ systemAppearance: void 0,
365
+ foreground: void 0,
366
+ background: void 0,
367
+ cursor: void 0,
368
+ palette: void 0
369
+ }
370
+ };
371
+ }
372
+ //#endregion
373
+ export { detectTerminal as a, signalExit as c, detectHyperlinkSupport as i, detectCapabilities as n, detectUnicodeSupport as o, detectColorLevel as r, terminalSize as s, createSupportsColor as t };
@@ -0,0 +1,9 @@
1
+ //#region src/env.ts
2
+ const isInCi = Boolean(process.env.CI);
3
+ const isSigilDev = process.env.SIGIL_DEV === "true";
4
+ const isScreenReader = process.env.SIGIL_SCREEN_READER === "true";
5
+ const isWindows = process.platform === "win32";
6
+ const isMacos = process.platform === "darwin";
7
+ const isTty = (stream) => "isTTY" in stream && stream.isTTY === true;
8
+ //#endregion
9
+ export { isTty as a, isSigilDev as i, isMacos as n, isWindows as o, isScreenReader as r, isInCi as t };
@@ -0,0 +1,72 @@
1
+ //#region src/ansi/escapes.d.ts
2
+ declare const ESC = "";
3
+ declare const BEL = "";
4
+ declare const DEL = "";
5
+ /** Control Sequence Introducer. */
6
+ declare const CSI = "[";
7
+ /** Operating System Command. */
8
+ declare const OSC = "]";
9
+ /** String Terminator. */
10
+ declare const ST = "\\";
11
+ /** Single-byte C1 forms of CSI and ST. */
12
+ declare const C1_CSI = "›";
13
+ declare const C1_ST = "œ";
14
+ declare const cursorTo: (x: number, y?: number) => string;
15
+ declare const cursorUp: (count?: number) => string;
16
+ declare const cursorDown: (count?: number) => string;
17
+ declare const cursorLeft: string;
18
+ declare const cursorNextLine: string;
19
+ declare const eraseEndLine: string;
20
+ declare const eraseLine: string;
21
+ declare const eraseScreen: string;
22
+ declare const eraseLines: (count: number) => string;
23
+ declare const clearTerminal = "";
24
+ declare const enterAlternativeScreen: string;
25
+ declare const exitAlternativeScreen: string;
26
+ declare const cursorShow: string;
27
+ declare const cursorHide: string;
28
+ type CursorShape = "block" | "underline" | "bar";
29
+ declare const cursorShape: (shape: CursorShape, blinking?: boolean) => string;
30
+ declare const cursorColor: (color: string) => string;
31
+ declare const resetCursorColor = "]112";
32
+ declare const enableBracketedPaste: string;
33
+ declare const disableBracketedPaste: string;
34
+ declare const pasteStart: string;
35
+ declare const pasteEnd: string;
36
+ declare const bsu: string;
37
+ declare const esu: string;
38
+ declare const kittyQuery: string;
39
+ declare const pushKittyKeyboard: (flags: number) => string;
40
+ declare const popKittyKeyboard: string;
41
+ declare const link: (text: string, url: string) => string;
42
+ declare const ansiEscapes: {
43
+ cursorTo: typeof cursorTo;
44
+ cursorUp: typeof cursorUp;
45
+ cursorDown: typeof cursorDown;
46
+ cursorLeft: string;
47
+ cursorNextLine: string;
48
+ eraseEndLine: string;
49
+ eraseLine: string;
50
+ eraseScreen: string;
51
+ eraseLines: typeof eraseLines;
52
+ clearTerminal: string;
53
+ enterAlternativeScreen: string;
54
+ exitAlternativeScreen: string;
55
+ cursorShow: string;
56
+ cursorHide: string;
57
+ cursorShape: typeof cursorShape;
58
+ cursorColor: typeof cursorColor;
59
+ resetCursorColor: string;
60
+ enableBracketedPaste: string;
61
+ disableBracketedPaste: string;
62
+ pasteStart: string;
63
+ pasteEnd: string;
64
+ bsu: string;
65
+ esu: string;
66
+ kittyQuery: string;
67
+ pushKittyKeyboard: typeof pushKittyKeyboard;
68
+ popKittyKeyboard: string;
69
+ link: typeof link;
70
+ };
71
+ //#endregion
72
+ export { exitAlternativeScreen as A, enableBracketedPaste as C, eraseLines as D, eraseLine as E, popKittyKeyboard as F, pushKittyKeyboard as I, resetCursorColor as L, link as M, pasteEnd as N, eraseScreen as O, pasteStart as P, disableBracketedPaste as S, eraseEndLine as T, cursorNextLine as _, CursorShape as a, cursorTo as b, OSC as c, bsu as d, clearTerminal as f, cursorLeft as g, cursorHide as h, CSI as i, kittyQuery as j, esu as k, ST as l, cursorDown as m, C1_CSI as n, DEL as o, cursorColor as p, C1_ST as r, ESC as s, BEL as t, ansiEscapes as u, cursorShape as v, enterAlternativeScreen as w, cursorUp as x, cursorShow as y };
@@ -0,0 +1,11 @@
1
+ //#region src/screen/geometry.d.ts
2
+ type Point = {
3
+ readonly x: number;
4
+ readonly y: number;
5
+ };
6
+ type Rect = Point & {
7
+ readonly width: number;
8
+ readonly height: number;
9
+ };
10
+ //#endregion
11
+ export { Rect as n, Point as t };