@teammates/consolonia 0.7.2 → 0.7.3

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.
@@ -4,7 +4,6 @@ import * as esc from "../ansi/esc.js";
4
4
  import { AnsiOutput } from "../ansi/output.js";
5
5
  import { stripAnsi, truncateAnsi, visibleLength } from "../ansi/strip.js";
6
6
  import { detectTerminal } from "../ansi/terminal-env.js";
7
- import { enableWin32Mouse, restoreWin32Console, } from "../ansi/win32-console.js";
8
7
  // ── Helpers ────────────────────────────────────────────────────────
9
8
  const ESC = "\x1b[";
10
9
  /** Build a mock writable stream that accumulates output to a string. */
@@ -815,33 +814,3 @@ describe("esc environment-aware sequences", () => {
815
814
  });
816
815
  });
817
816
  });
818
- // ═══════════════════════════════════════════════════════════════════
819
- // win32-console.ts
820
- // ═══════════════════════════════════════════════════════════════════
821
- describe("win32-console", () => {
822
- const originalPlatform = process.platform;
823
- afterEach(() => {
824
- Object.defineProperty(process, "platform", { value: originalPlatform });
825
- });
826
- describe("enableWin32Mouse", () => {
827
- it("returns false on non-win32 platforms", () => {
828
- Object.defineProperty(process, "platform", { value: "linux" });
829
- expect(enableWin32Mouse()).toBe(false);
830
- });
831
- it("returns false on darwin", () => {
832
- Object.defineProperty(process, "platform", { value: "darwin" });
833
- expect(enableWin32Mouse()).toBe(false);
834
- });
835
- });
836
- describe("restoreWin32Console", () => {
837
- it("returns false on non-win32 platforms", () => {
838
- Object.defineProperty(process, "platform", { value: "linux" });
839
- expect(restoreWin32Console()).toBe(false);
840
- });
841
- it("returns false when no original mode was saved", () => {
842
- // Even on win32, if enableWin32Mouse was never called, restore is a no-op
843
- Object.defineProperty(process, "platform", { value: "win32" });
844
- expect(restoreWin32Console()).toBe(false);
845
- });
846
- });
847
- });
@@ -296,6 +296,44 @@ describe("symbol", () => {
296
296
  // U+1F600 = grinning face (in emoji range 0x1f000-0x1faff)
297
297
  expect(charWidth(0x1f600)).toBe(2);
298
298
  });
299
+ it("text-presentation symbols that remain width 1", () => {
300
+ // These render as 1 cell even on Windows Terminal
301
+ expect(charWidth(0x2713)).toBe(1); // ✓ Check Mark
302
+ expect(charWidth(0x2702)).toBe(1); // ✂ Scissors
303
+ expect(charWidth(0x00a9)).toBe(1); // © Copyright
304
+ expect(charWidth(0x00ae)).toBe(1); // ® Registered
305
+ });
306
+ it("emoji-presentation symbols are width 2", () => {
307
+ // These have Emoji_Presentation=Yes and render as 2 cells
308
+ expect(charWidth(0x2614)).toBe(2); // ☔ Umbrella with Rain Drops
309
+ expect(charWidth(0x2615)).toBe(2); // ☕ Hot Beverage
310
+ expect(charWidth(0x2705)).toBe(2); // ✅ White Heavy Check Mark
311
+ expect(charWidth(0x274c)).toBe(2); // ❌ Cross Mark
312
+ expect(charWidth(0x2757)).toBe(2); // ❗ Heavy Exclamation Mark
313
+ expect(charWidth(0x26bd)).toBe(2); // ⚽ Soccer Ball
314
+ expect(charWidth(0x26fd)).toBe(2); // ⛽ Fuel Pump
315
+ expect(charWidth(0x2b50)).toBe(2); // ⭐ White Medium Star
316
+ });
317
+ it("Windows Terminal wide symbols are width 2", () => {
318
+ // Text-presentation chars that Windows Terminal renders as double-width
319
+ expect(charWidth(0x2139)).toBe(2); // ℹ Information Source
320
+ expect(charWidth(0x2605)).toBe(2); // ★ Black Star
321
+ expect(charWidth(0x2606)).toBe(2); // ☆ White Star
322
+ expect(charWidth(0x2660)).toBe(2); // ♠ Black Spade Suit
323
+ expect(charWidth(0x2663)).toBe(2); // ♣ Black Club Suit
324
+ expect(charWidth(0x2665)).toBe(2); // ♥ Black Heart Suit
325
+ expect(charWidth(0x2666)).toBe(2); // ♦ Black Diamond Suit
326
+ expect(charWidth(0x2690)).toBe(2); // ⚐ White Flag
327
+ expect(charWidth(0x2691)).toBe(2); // ⚑ Black Flag
328
+ expect(charWidth(0x2699)).toBe(2); // ⚙ Gear
329
+ expect(charWidth(0x26a0)).toBe(2); // ⚠ Warning Sign
330
+ expect(charWidth(0x2714)).toBe(2); // ✔ Heavy Check Mark
331
+ expect(charWidth(0x2716)).toBe(2); // ✖ Heavy Multiplication X
332
+ expect(charWidth(0x279c)).toBe(2); // ➜ Heavy Round-Tipped Arrow
333
+ expect(charWidth(0x27a4)).toBe(2); // ➤ Black Right Arrowhead
334
+ expect(charWidth(0x25b6)).toBe(2); // ▶ Black Right Triangle
335
+ expect(charWidth(0x23f1)).toBe(2); // ⏱ Stopwatch
336
+ });
299
337
  });
300
338
  describe("sym() factory", () => {
301
339
  it("creates a symbol with auto-detected width 1 for ASCII", () => {
@@ -80,7 +80,7 @@ describe("concat", () => {
80
80
  const s = concat(pen.green("✔ "), pen.white("done"));
81
81
  expect(s).toHaveLength(2);
82
82
  expect(spanText(s)).toBe("✔ done");
83
- expect(spanLength(s)).toBe(7); // ✔ is width 2 (dingbat emoji)
83
+ expect(spanLength(s)).toBe(7); // ✔ is width 2 (renders wide on Windows Terminal)
84
84
  });
85
85
  it("accepts plain strings", () => {
86
86
  const s = concat("hello ", pen.cyan("world"));
package/dist/app.js CHANGED
@@ -8,7 +8,6 @@
8
8
  import * as esc from "./ansi/esc.js";
9
9
  import { AnsiOutput } from "./ansi/output.js";
10
10
  import { detectTerminal } from "./ansi/terminal-env.js";
11
- import { enableWin32Mouse, restoreWin32Console } from "./ansi/win32-console.js";
12
11
  import { DrawingContext } from "./drawing/context.js";
13
12
  import { createInputProcessor } from "./input/processor.js";
14
13
  import { disableRawMode, enableRawMode } from "./input/raw-mode.js";
@@ -98,30 +97,24 @@ export class App {
98
97
  const stdout = process.stdout;
99
98
  // 1. Enable raw mode
100
99
  enableRawMode();
101
- // 2. On Windows, configure console mode for mouse input
102
- // (must happen after raw mode so we modify the right base flags)
103
- if (this._mouse) {
104
- enableWin32Mouse();
105
- }
106
- // 3. Create ANSI output
100
+ // 2. Create ANSI output
107
101
  this._output = new AnsiOutput(stdout);
108
- // 4. Prepare terminal (custom sequence instead of prepareTerminal()
109
- // so we can conditionally enable mouse tracking)
102
+ // 3. Prepare terminal (ANSI sequences for alternate screen, mouse, etc.)
110
103
  this._prepareTerminal();
111
- // 5. Set terminal title
104
+ // 4. Set terminal title
112
105
  if (this._title) {
113
106
  stdout.write(esc.setTitle(this._title));
114
107
  }
115
- // 6. Create pixel buffer at terminal dimensions
108
+ // 5. Create pixel buffer at terminal dimensions
116
109
  const cols = stdout.columns || 80;
117
110
  const rows = stdout.rows || 24;
118
111
  this._createRenderPipeline(cols, rows);
119
- // 7. Wire up input
112
+ // 6. Wire up input
120
113
  this._setupInput();
121
- // 8. Wire up resize
114
+ // 7. Wire up resize
122
115
  this._resizeListener = () => this._handleResize();
123
116
  stdout.on("resize", this._resizeListener);
124
- // 9. SIGINT fallback
117
+ // 8. SIGINT fallback
125
118
  this._sigintListener = () => this.stop();
126
119
  process.on("SIGINT", this._sigintListener);
127
120
  }
@@ -300,8 +293,6 @@ export class App {
300
293
  }
301
294
  // Restore terminal
302
295
  this._restoreTerminal();
303
- // Restore Win32 console mode (before disabling raw mode)
304
- restoreWin32Console();
305
296
  // Disable raw mode
306
297
  disableRawMode();
307
298
  // Resolve the run() promise
package/dist/index.d.ts CHANGED
@@ -17,7 +17,6 @@ export * as esc from "./ansi/esc.js";
17
17
  export { AnsiOutput } from "./ansi/output.js";
18
18
  export { stripAnsi, truncateAnsi, visibleLength, } from "./ansi/strip.js";
19
19
  export { detectTerminal, type TerminalCaps, } from "./ansi/terminal-env.js";
20
- export { enableWin32Mouse, restoreWin32Console, } from "./ansi/win32-console.js";
21
20
  export { DirtyRegions, DirtySnapshot } from "./render/regions.js";
22
21
  export { RenderTarget } from "./render/render-target.js";
23
22
  export { EscapeMatcher } from "./input/escape-matcher.js";
package/dist/index.js CHANGED
@@ -24,7 +24,6 @@ export * as esc from "./ansi/esc.js";
24
24
  export { AnsiOutput } from "./ansi/output.js";
25
25
  export { stripAnsi, truncateAnsi, visibleLength, } from "./ansi/strip.js";
26
26
  export { detectTerminal, } from "./ansi/terminal-env.js";
27
- export { enableWin32Mouse, restoreWin32Console, } from "./ansi/win32-console.js";
28
27
  // ── Render pipeline ─────────────────────────────────────────────────
29
28
  export { DirtyRegions, DirtySnapshot } from "./render/regions.js";
30
29
  export { RenderTarget } from "./render/render-target.js";
@@ -114,49 +114,115 @@ export function charWidth(codePoint) {
114
114
  // CJK Compatibility Ideographs Supplement
115
115
  if (codePoint >= 0x2f800 && codePoint <= 0x2fa1f)
116
116
  return 2;
117
- // ── Emoji ranges (rendered as width 2 on modern terminals) ─────
118
- // Hourglass + Watch
117
+ // ── Emoji with Emoji_Presentation=Yes (rendered as 2 cells by default) ──
118
+ // Only characters that terminals render as wide WITHOUT a variation selector.
119
+ // ── Text-presentation characters that Windows Terminal renders as wide ──
120
+ // These have Emoji_Presentation=No in Unicode but modern terminals (Windows
121
+ // Terminal, VS Code integrated terminal) render them as double-width emoji.
122
+ if (codePoint === 0x2139)
123
+ return 2; // ℹ Information Source
124
+ if (codePoint === 0x2605 || codePoint === 0x2606)
125
+ return 2; // ★☆ Stars
126
+ if (codePoint === 0x2660)
127
+ return 2; // ♠ Black Spade Suit
128
+ if (codePoint === 0x2663)
129
+ return 2; // ♣ Black Club Suit
130
+ if (codePoint === 0x2665)
131
+ return 2; // ♥ Black Heart Suit
132
+ if (codePoint === 0x2666)
133
+ return 2; // ♦ Black Diamond Suit
134
+ if (codePoint === 0x2690 || codePoint === 0x2691)
135
+ return 2; // ⚐⚑ Flags
136
+ if (codePoint === 0x2699)
137
+ return 2; // ⚙ Gear
138
+ if (codePoint === 0x26a0)
139
+ return 2; // ⚠ Warning Sign
140
+ if (codePoint === 0x2714)
141
+ return 2; // ✔ Heavy Check Mark
142
+ if (codePoint === 0x2716)
143
+ return 2; // ✖ Heavy Multiplication X
144
+ if (codePoint === 0x279c)
145
+ return 2; // ➜ Heavy Round-Tipped Arrow
146
+ if (codePoint === 0x27a4)
147
+ return 2; // ➤ Black Right Arrowhead
148
+ if (codePoint === 0x25b6)
149
+ return 2; // ▶ Black Right Triangle
150
+ if (codePoint === 0x23f1)
151
+ return 2; // ⏱ Stopwatch
152
+ // Hourglass + Watch (⌚⌛)
119
153
  if (codePoint === 0x231a || codePoint === 0x231b)
120
154
  return 2;
121
- // Player controls (⏩-⏳)
122
- if (codePoint >= 0x23e9 && codePoint <= 0x23f3)
123
- return 2;
124
- // Media controls (⏸-⏺)
125
- if (codePoint >= 0x23f8 && codePoint <= 0x23fa)
126
- return 2;
127
- // Play / reverse play buttons
128
- if (codePoint === 0x25b6 || codePoint === 0x25c0)
129
- return 2;
130
- // Geometric shapes used as emoji (◻◼◽◾)
131
- if (codePoint >= 0x25fb && codePoint <= 0x25fe)
132
- return 2;
133
- // Miscellaneous Symbols — most have emoji presentation (☀-⛿)
134
- if (codePoint >= 0x2600 && codePoint <= 0x26ff)
135
- return 2;
136
- // Dingbats with emoji presentation (✂-➿)
137
- if (codePoint >= 0x2702 && codePoint <= 0x27b0)
138
- return 2;
139
- // Curly loop
140
- if (codePoint === 0x27bf)
141
- return 2;
142
- // Supplemental arrows used as emoji
143
- if (codePoint === 0x2934 || codePoint === 0x2935)
144
- return 2;
145
- // Misc symbols used as emoji (⬛⬜⭐⭕)
146
- if (codePoint >= 0x2b05 && codePoint <= 0x2b07)
147
- return 2;
155
+ // Fast-forward through rewind (⏩⏪⏫⏬)
156
+ if (codePoint >= 0x23e9 && codePoint <= 0x23ec)
157
+ return 2;
158
+ // Alarm clock ()
159
+ if (codePoint === 0x23f0)
160
+ return 2;
161
+ // Hourglass flowing (⏳)
162
+ if (codePoint === 0x23f3)
163
+ return 2;
164
+ // White/black medium small square with emoji pres (◽◾)
165
+ if (codePoint === 0x25fd || codePoint === 0x25fe)
166
+ return 2;
167
+ // Misc Symbols — only Emoji_Presentation=Yes entries
168
+ if (codePoint === 0x2614 || codePoint === 0x2615)
169
+ return 2; // ☔☕
170
+ if (codePoint >= 0x2648 && codePoint <= 0x2653)
171
+ return 2; // ♈-♓
172
+ if (codePoint === 0x267f)
173
+ return 2; //
174
+ if (codePoint === 0x2693)
175
+ return 2; // ⚓
176
+ if (codePoint === 0x26a1)
177
+ return 2; //
178
+ if (codePoint === 0x26aa || codePoint === 0x26ab)
179
+ return 2; // ⚪⚫
180
+ if (codePoint === 0x26bd || codePoint === 0x26be)
181
+ return 2; // ⚽⚾
182
+ if (codePoint === 0x26c4 || codePoint === 0x26c5)
183
+ return 2; // ⛄⛅
184
+ if (codePoint === 0x26ce)
185
+ return 2; // ⛎
186
+ if (codePoint === 0x26d4)
187
+ return 2; // ⛔
188
+ if (codePoint === 0x26ea)
189
+ return 2; // ⛪
190
+ if (codePoint === 0x26f2 || codePoint === 0x26f3)
191
+ return 2; // ⛲⛳
192
+ if (codePoint === 0x26f5)
193
+ return 2; // ⛵
194
+ if (codePoint === 0x26fa)
195
+ return 2; // ⛺
196
+ if (codePoint === 0x26fd)
197
+ return 2; // ⛽
198
+ // Dingbats — only Emoji_Presentation=Yes entries
199
+ if (codePoint === 0x2705)
200
+ return 2; // ✅
201
+ if (codePoint === 0x270a || codePoint === 0x270b)
202
+ return 2; // ✊✋
203
+ if (codePoint === 0x2728)
204
+ return 2; // ✨
205
+ if (codePoint === 0x274c)
206
+ return 2; // ❌
207
+ if (codePoint === 0x274e)
208
+ return 2; // ❎
209
+ if (codePoint >= 0x2753 && codePoint <= 0x2755)
210
+ return 2; // ❓❔❕
211
+ if (codePoint === 0x2757)
212
+ return 2; // ❗
213
+ if (codePoint === 0x2764)
214
+ return 2; // ❤
215
+ if (codePoint >= 0x2795 && codePoint <= 0x2797)
216
+ return 2; // ➕➖➗
217
+ // Curly loop / double curly loop (➰➿)
218
+ if (codePoint === 0x27b0 || codePoint === 0x27bf)
219
+ return 2;
220
+ // Black large square/circle, star, hollow circle (⬛⬜⭐⭕)
148
221
  if (codePoint === 0x2b1b || codePoint === 0x2b1c)
149
222
  return 2;
150
223
  if (codePoint === 0x2b50 || codePoint === 0x2b55)
151
224
  return 2;
152
- // Copyright / Registered / TM (when emoji-styled)
153
- if (codePoint === 0x00a9 || codePoint === 0x00ae)
154
- return 2;
155
- // Wavy dash, part alternation mark
156
- if (codePoint === 0x3030 || codePoint === 0x303d)
157
- return 2;
158
225
  // SMP Emoji: Mahjong through Symbols & Pictographs Extended-A
159
- // Covers emoticons, transport, flags, supplemental symbols, etc.
160
226
  if (codePoint >= 0x1f000 && codePoint <= 0x1faff)
161
227
  return 2;
162
228
  return 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teammates/consolonia",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Terminal UI rendering engine inspired by Consolonia. Pixel-level compositing with ANSI output.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -41,8 +41,5 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "marked": "^17.0.4"
44
- },
45
- "optionalDependencies": {
46
- "koffi": "^2.9.0"
47
44
  }
48
45
  }
@@ -1,28 +0,0 @@
1
- /**
2
- * Win32 Console Mode — enables mouse input on Windows terminals.
3
- *
4
- * Node.js `setRawMode(true)` enables ENABLE_VIRTUAL_TERMINAL_INPUT but
5
- * does NOT disable ENABLE_QUICK_EDIT_MODE (which intercepts mouse clicks
6
- * for text selection) or enable ENABLE_MOUSE_INPUT. This module uses
7
- * koffi to call the Win32 API directly and set the correct flags.
8
- *
9
- * Only loaded on win32 — no-ops on other platforms.
10
- */
11
- /**
12
- * Configure the Windows console for mouse input.
13
- *
14
- * Disables Quick Edit Mode (which swallows mouse clicks) and enables
15
- * ENABLE_MOUSE_INPUT + ENABLE_EXTENDED_FLAGS + ENABLE_WINDOW_INPUT.
16
- * Saves the original mode so it can be restored later.
17
- *
18
- * No-op on non-Windows platforms or if koffi is not available.
19
- * Returns true if the mode was successfully changed.
20
- */
21
- export declare function enableWin32Mouse(): boolean;
22
- /**
23
- * Restore the original Windows console mode saved by enableWin32Mouse().
24
- *
25
- * No-op if enableWin32Mouse() was never called or failed.
26
- * Returns true if the mode was successfully restored.
27
- */
28
- export declare function restoreWin32Console(): boolean;
@@ -1,122 +0,0 @@
1
- /**
2
- * Win32 Console Mode — enables mouse input on Windows terminals.
3
- *
4
- * Node.js `setRawMode(true)` enables ENABLE_VIRTUAL_TERMINAL_INPUT but
5
- * does NOT disable ENABLE_QUICK_EDIT_MODE (which intercepts mouse clicks
6
- * for text selection) or enable ENABLE_MOUSE_INPUT. This module uses
7
- * koffi to call the Win32 API directly and set the correct flags.
8
- *
9
- * Only loaded on win32 — no-ops on other platforms.
10
- */
11
- import { createRequire } from "node:module";
12
- // ── Console mode flag constants ─────────────────────────────────────
13
- const ENABLE_PROCESSED_INPUT = 0x0001;
14
- const ENABLE_LINE_INPUT = 0x0002;
15
- const ENABLE_ECHO_INPUT = 0x0004;
16
- const ENABLE_WINDOW_INPUT = 0x0008;
17
- const ENABLE_MOUSE_INPUT = 0x0010;
18
- const ENABLE_QUICK_EDIT_MODE = 0x0040;
19
- const ENABLE_EXTENDED_FLAGS = 0x0080;
20
- const ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200;
21
- const STD_INPUT_HANDLE = -10;
22
- // ── State ───────────────────────────────────────────────────────────
23
- let originalMode = null;
24
- let _kernel32;
25
- function getKernel32() {
26
- if (_kernel32 !== undefined)
27
- return _kernel32;
28
- try {
29
- // koffi is an optional native dependency — dynamic require so the
30
- // module loads cleanly even when koffi is absent.
31
- const require = createRequire(import.meta.url);
32
- const koffi = require("koffi");
33
- const lib = koffi.load("kernel32.dll");
34
- _kernel32 = {
35
- GetStdHandle: lib.func("void* __stdcall GetStdHandle(int nStdHandle)"),
36
- GetConsoleMode: lib.func("bool __stdcall GetConsoleMode(void* hConsoleHandle, _Out_ uint32_t* lpMode)"),
37
- SetConsoleMode: lib.func("bool __stdcall SetConsoleMode(void* hConsoleHandle, uint32_t dwMode)"),
38
- };
39
- }
40
- catch {
41
- _kernel32 = null;
42
- }
43
- return _kernel32;
44
- }
45
- // ── Public API ──────────────────────────────────────────────────────
46
- /**
47
- * Configure the Windows console for mouse input.
48
- *
49
- * Disables Quick Edit Mode (which swallows mouse clicks) and enables
50
- * ENABLE_MOUSE_INPUT + ENABLE_EXTENDED_FLAGS + ENABLE_WINDOW_INPUT.
51
- * Saves the original mode so it can be restored later.
52
- *
53
- * No-op on non-Windows platforms or if koffi is not available.
54
- * Returns true if the mode was successfully changed.
55
- */
56
- export function enableWin32Mouse() {
57
- if (process.platform !== "win32")
58
- return false;
59
- const k32 = getKernel32();
60
- if (!k32)
61
- return false;
62
- try {
63
- const handle = k32.GetStdHandle(STD_INPUT_HANDLE);
64
- if (!handle)
65
- return false;
66
- // Read current mode
67
- const modeBuffer = Buffer.alloc(4);
68
- if (!k32.GetConsoleMode(handle, modeBuffer))
69
- return false;
70
- originalMode = modeBuffer.readUInt32LE(0);
71
- // Build new mode:
72
- // - Keep ENABLE_VIRTUAL_TERMINAL_INPUT (set by Node raw mode)
73
- // - Add ENABLE_MOUSE_INPUT + ENABLE_WINDOW_INPUT + ENABLE_EXTENDED_FLAGS
74
- // - Remove ENABLE_QUICK_EDIT_MODE
75
- // - Remove line/echo/processed (already cleared by raw mode)
76
- let newMode = originalMode;
77
- newMode |= ENABLE_MOUSE_INPUT;
78
- newMode |= ENABLE_WINDOW_INPUT;
79
- newMode |= ENABLE_EXTENDED_FLAGS;
80
- newMode &= ~ENABLE_QUICK_EDIT_MODE;
81
- newMode &= ~ENABLE_LINE_INPUT;
82
- newMode &= ~ENABLE_ECHO_INPUT;
83
- newMode &= ~ENABLE_PROCESSED_INPUT;
84
- // Preserve VT input if it was set
85
- if (originalMode & ENABLE_VIRTUAL_TERMINAL_INPUT) {
86
- newMode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
87
- }
88
- return k32.SetConsoleMode(handle, newMode);
89
- }
90
- catch {
91
- return false;
92
- }
93
- }
94
- /**
95
- * Restore the original Windows console mode saved by enableWin32Mouse().
96
- *
97
- * No-op if enableWin32Mouse() was never called or failed.
98
- * Returns true if the mode was successfully restored.
99
- */
100
- export function restoreWin32Console() {
101
- if (process.platform !== "win32" || originalMode === null)
102
- return false;
103
- const k32 = getKernel32();
104
- if (!k32) {
105
- originalMode = null;
106
- return false;
107
- }
108
- try {
109
- const handle = k32.GetStdHandle(STD_INPUT_HANDLE);
110
- if (!handle) {
111
- originalMode = null;
112
- return false;
113
- }
114
- const result = k32.SetConsoleMode(handle, originalMode);
115
- originalMode = null;
116
- return result;
117
- }
118
- catch {
119
- originalMode = null;
120
- return false;
121
- }
122
- }