novac 2.0.1 → 2.2.0

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 (161) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1574 -597
  3. package/bin/novac +468 -171
  4. package/bin/nvc +522 -0
  5. package/bin/nvml +78 -17
  6. package/demo.nv +0 -0
  7. package/demo_builtins.nv +0 -0
  8. package/demo_http.nv +0 -0
  9. package/examples/bf.nv +69 -0
  10. package/examples/math.nv +21 -0
  11. package/kits/birdAPI/kitdef.js +954 -0
  12. package/kits/kitRNG/kitdef.js +740 -0
  13. package/kits/kitSSH/kitdef.js +1272 -0
  14. package/kits/kitadb/kitdef.js +606 -0
  15. package/kits/kitai/kitdef.js +2185 -0
  16. package/kits/kitansi/kitdef.js +1402 -0
  17. package/kits/kitcanvas/kitdef.js +914 -0
  18. package/kits/kitclippy/kitdef.js +925 -0
  19. package/kits/kitformat/kitdef.js +1485 -0
  20. package/kits/kitgps/kitdef.js +1862 -0
  21. package/kits/kitlibproc/kitdef.js +3 -2
  22. package/kits/kitmatrix/ex.js +19 -0
  23. package/kits/kitmatrix/kitdef.js +960 -0
  24. package/kits/kitmorse/kitdef.js +229 -0
  25. package/kits/kitmpatch/kitdef.js +906 -0
  26. package/kits/kitnet/kitdef.js +1401 -0
  27. package/kits/kitnovacweb/README.md +1416 -143
  28. package/kits/kitnovacweb/kitdef.js +92 -2
  29. package/kits/kitnovacweb/nvml/executor.js +578 -176
  30. package/kits/kitnovacweb/nvml/index.js +2 -2
  31. package/kits/kitnovacweb/nvml/lexer.js +72 -69
  32. package/kits/kitnovacweb/nvml/parser.js +328 -159
  33. package/kits/kitnovacweb/nvml/renderer.js +770 -270
  34. package/kits/kitparse/kitdef.js +1688 -0
  35. package/kits/kitproto/kitdef.js +613 -0
  36. package/kits/kitqr/kitdef.js +637 -0
  37. package/kits/kitregex++/kitdef.js +1353 -0
  38. package/kits/kitrequire/kitdef.js +1599 -0
  39. package/kits/kitx11/kitdef.js +1 -0
  40. package/kits/kitx11/kitx11.js +2472 -0
  41. package/kits/kitx11/kitx11_conn.js +948 -0
  42. package/kits/kitx11/kitx11_worker.js +121 -0
  43. package/kits/libtea/kitdef.js +2691 -0
  44. package/kits/libterm/ex.js +285 -0
  45. package/kits/libterm/kitdef.js +1927 -0
  46. package/novac/LICENSE +21 -0
  47. package/novac/README.md +1823 -0
  48. package/novac/bin/novac +950 -0
  49. package/novac/bin/nvc +522 -0
  50. package/novac/bin/nvml +542 -0
  51. package/novac/demo.nv +245 -0
  52. package/novac/demo_builtins.nv +209 -0
  53. package/novac/demo_http.nv +62 -0
  54. package/novac/examples/bf.nv +69 -0
  55. package/novac/examples/math.nv +21 -0
  56. package/novac/kits/kitai/kitdef.js +2185 -0
  57. package/novac/kits/kitansi/kitdef.js +1402 -0
  58. package/novac/kits/kitformat/kitdef.js +1485 -0
  59. package/novac/kits/kitgps/kitdef.js +1862 -0
  60. package/novac/kits/kitlibfs/kitdef.js +231 -0
  61. package/{examples/example-project/nova_modules → novac/kits}/kitlibproc/kitdef.js +3 -2
  62. package/novac/kits/kitmatrix/ex.js +19 -0
  63. package/novac/kits/kitmatrix/kitdef.js +960 -0
  64. package/novac/kits/kitmpatch/kitdef.js +906 -0
  65. package/novac/kits/kitnovacweb/README.md +1572 -0
  66. package/novac/kits/kitnovacweb/demo.nv +12 -0
  67. package/novac/kits/kitnovacweb/demo.nvml +71 -0
  68. package/novac/kits/kitnovacweb/index.nova +12 -0
  69. package/novac/kits/kitnovacweb/kitdef.js +692 -0
  70. package/novac/kits/kitnovacweb/nova.kit.json +8 -0
  71. package/novac/kits/kitnovacweb/nvml/executor.js +739 -0
  72. package/novac/kits/kitnovacweb/nvml/index.js +67 -0
  73. package/novac/kits/kitnovacweb/nvml/lexer.js +263 -0
  74. package/novac/kits/kitnovacweb/nvml/parser.js +508 -0
  75. package/novac/kits/kitnovacweb/nvml/renderer.js +924 -0
  76. package/novac/kits/kitparse/kitdef.js +1688 -0
  77. package/novac/kits/kitregex++/kitdef.js +1353 -0
  78. package/novac/kits/kitrequire/kitdef.js +1599 -0
  79. package/novac/kits/kitx11/kitdef.js +1 -0
  80. package/novac/kits/kitx11/kitx11.js +2472 -0
  81. package/novac/kits/kitx11/kitx11_conn.js +948 -0
  82. package/novac/kits/kitx11/kitx11_worker.js +121 -0
  83. package/novac/kits/libtea/tf.js +2691 -0
  84. package/novac/kits/libterm/ex.js +285 -0
  85. package/novac/kits/libterm/kitdef.js +1927 -0
  86. package/novac/node_modules/chalk/license +9 -0
  87. package/novac/node_modules/chalk/package.json +83 -0
  88. package/novac/node_modules/chalk/readme.md +297 -0
  89. package/novac/node_modules/chalk/source/index.d.ts +325 -0
  90. package/novac/node_modules/chalk/source/index.js +225 -0
  91. package/novac/node_modules/chalk/source/utilities.js +33 -0
  92. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.d.ts +236 -0
  93. package/novac/node_modules/chalk/source/vendor/ansi-styles/index.js +223 -0
  94. package/novac/node_modules/chalk/source/vendor/supports-color/browser.d.ts +1 -0
  95. package/novac/node_modules/chalk/source/vendor/supports-color/browser.js +34 -0
  96. package/novac/node_modules/chalk/source/vendor/supports-color/index.d.ts +55 -0
  97. package/novac/node_modules/chalk/source/vendor/supports-color/index.js +190 -0
  98. package/novac/node_modules/commander/LICENSE +22 -0
  99. package/novac/node_modules/commander/Readme.md +1176 -0
  100. package/novac/node_modules/commander/esm.mjs +16 -0
  101. package/novac/node_modules/commander/index.js +24 -0
  102. package/novac/node_modules/commander/lib/argument.js +150 -0
  103. package/novac/node_modules/commander/lib/command.js +2777 -0
  104. package/novac/node_modules/commander/lib/error.js +39 -0
  105. package/novac/node_modules/commander/lib/help.js +747 -0
  106. package/novac/node_modules/commander/lib/option.js +380 -0
  107. package/novac/node_modules/commander/lib/suggestSimilar.js +101 -0
  108. package/novac/node_modules/commander/package-support.json +19 -0
  109. package/novac/node_modules/commander/package.json +82 -0
  110. package/novac/node_modules/commander/typings/esm.d.mts +3 -0
  111. package/novac/node_modules/commander/typings/index.d.ts +1113 -0
  112. package/novac/node_modules/node-addon-api/LICENSE.md +9 -0
  113. package/novac/node_modules/node-addon-api/README.md +95 -0
  114. package/novac/node_modules/node-addon-api/common.gypi +21 -0
  115. package/novac/node_modules/node-addon-api/except.gypi +25 -0
  116. package/novac/node_modules/node-addon-api/index.js +14 -0
  117. package/novac/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
  118. package/novac/node_modules/node-addon-api/napi-inl.h +7165 -0
  119. package/novac/node_modules/node-addon-api/napi.h +3364 -0
  120. package/novac/node_modules/node-addon-api/node_addon_api.gyp +42 -0
  121. package/novac/node_modules/node-addon-api/node_api.gyp +9 -0
  122. package/novac/node_modules/node-addon-api/noexcept.gypi +26 -0
  123. package/novac/node_modules/node-addon-api/package-support.json +21 -0
  124. package/novac/node_modules/node-addon-api/package.json +480 -0
  125. package/novac/node_modules/node-addon-api/tools/README.md +73 -0
  126. package/novac/node_modules/node-addon-api/tools/check-napi.js +99 -0
  127. package/novac/node_modules/node-addon-api/tools/clang-format.js +71 -0
  128. package/novac/node_modules/node-addon-api/tools/conversion.js +301 -0
  129. package/novac/node_modules/serialize-javascript/LICENSE +27 -0
  130. package/novac/node_modules/serialize-javascript/README.md +149 -0
  131. package/novac/node_modules/serialize-javascript/index.js +297 -0
  132. package/novac/node_modules/serialize-javascript/package.json +33 -0
  133. package/novac/package.json +27 -0
  134. package/novac/scripts/update-bin.js +24 -0
  135. package/novac/src/core/bstd.js +1035 -0
  136. package/novac/src/core/config.js +155 -0
  137. package/novac/src/core/describe.js +187 -0
  138. package/novac/src/core/emitter.js +499 -0
  139. package/novac/src/core/error.js +86 -0
  140. package/novac/src/core/executor.js +5606 -0
  141. package/novac/src/core/formatter.js +686 -0
  142. package/novac/src/core/lexer.js +1026 -0
  143. package/novac/src/core/nova_builtins.js +717 -0
  144. package/novac/src/core/nova_thread_worker.js +166 -0
  145. package/novac/src/core/parser.js +2181 -0
  146. package/novac/src/core/types.js +112 -0
  147. package/novac/src/index.js +28 -0
  148. package/novac/src/runtime/stdlib.js +244 -0
  149. package/package.json +6 -3
  150. package/scripts/update-bin.js +0 -0
  151. package/src/core/bstd.js +838 -362
  152. package/src/core/executor.js +2578 -170
  153. package/src/core/lexer.js +502 -54
  154. package/src/core/nova_builtins.js +21 -3
  155. package/src/core/parser.js +413 -72
  156. package/src/core/types.js +30 -2
  157. package/src/index.js +0 -0
  158. package/examples/example-project/README.md +0 -3
  159. package/examples/example-project/src/main.nova +0 -3
  160. package/src/core/environment.js +0 -0
  161. /package/{examples/example-project/bin/example-project.nv → novac/node_modules/node-addon-api/nothing.c} +0 -0
@@ -0,0 +1,1402 @@
1
+ 'use strict';
2
+
3
+ // ============================================================
4
+ // kitansi.js — Full ANSI escape sequence kit
5
+ // Every sequence. Every control. Every color system.
6
+ // module.exports = { kitdef: { ...all exports } }
7
+ // ============================================================
8
+
9
+ // ────────────────────────────────────────────────────────────
10
+ // SECTION 1: CORE ESCAPE PRIMITIVES
11
+ // ────────────────────────────────────────────────────────────
12
+
13
+ const ESC = '\x1b'; // Escape character
14
+ const CSI = '\x1b['; // Control Sequence Introducer
15
+ const OSC = '\x1b]'; // Operating System Command
16
+ const DCS = '\x1bP'; // Device Control String
17
+ const ST = '\x1b\\'; // String Terminator
18
+ const BEL = '\x07'; // Bell character (alt ST for OSC)
19
+ const SS3 = '\x1bO'; // Single Shift Three
20
+ const PM = '\x1b^'; // Privacy Message
21
+ const APC = '\x1b_'; // Application Program Command
22
+
23
+ /**
24
+ * Raw CSI sequence builder.
25
+ * @param {string} code
26
+ * @returns {string}
27
+ */
28
+ function csi(code) { return CSI + code; }
29
+
30
+ /**
31
+ * Raw OSC sequence builder.
32
+ * @param {string} code
33
+ * @returns {string}
34
+ */
35
+ function osc(code) { return OSC + code + BEL; }
36
+
37
+ /**
38
+ * Raw OSC sequence with ST terminator instead of BEL.
39
+ */
40
+ function oscST(code) { return OSC + code + ST; }
41
+
42
+ // ────────────────────────────────────────────────────────────
43
+ // SECTION 2: SGR — SELECT GRAPHIC RENDITION (styles/colors)
44
+ // ────────────────────────────────────────────────────────────
45
+
46
+ /**
47
+ * Build a CSI SGR sequence from numeric codes.
48
+ * @param {...number} codes
49
+ * @returns {string}
50
+ */
51
+ function sgr(...codes) { return CSI + codes.join(';') + 'm'; }
52
+
53
+ // ── Reset ────────────────────────────────────────────────────
54
+
55
+ const RESET = sgr(0); // Reset all attributes
56
+ const RESET_FG = sgr(39); // Default foreground color
57
+ const RESET_BG = sgr(49); // Default background color
58
+ const RESET_UNDER = sgr(59); // Default underline color
59
+
60
+ // ── Text style codes ─────────────────────────────────────────
61
+
62
+ const Style = {
63
+ RESET: sgr(0),
64
+ BOLD: sgr(1),
65
+ DIM: sgr(2),
66
+ ITALIC: sgr(3),
67
+ UNDERLINE: sgr(4),
68
+ BLINK: sgr(5), // Slow blink (<150/min)
69
+ BLINK_FAST: sgr(6), // Rapid blink (≥150/min, limited support)
70
+ INVERSE: sgr(7), // Swap fg/bg
71
+ HIDDEN: sgr(8), // Invisible (conceal)
72
+ STRIKE: sgr(9), // Strikethrough
73
+ FONT_DEFAULT: sgr(10), // Primary font
74
+ FONT_ALT_1: sgr(11),
75
+ FONT_ALT_2: sgr(12),
76
+ FONT_ALT_3: sgr(13),
77
+ FONT_ALT_4: sgr(14),
78
+ FONT_ALT_5: sgr(15),
79
+ FONT_ALT_6: sgr(16),
80
+ FONT_ALT_7: sgr(17),
81
+ FONT_ALT_8: sgr(18),
82
+ FONT_ALT_9: sgr(19),
83
+ FRAKTUR: sgr(20), // Gothic / Fraktur (rare)
84
+ BOLD_OFF: sgr(21), // Bold off (or double underline)
85
+ NORMAL: sgr(22), // Normal intensity (bold+dim off)
86
+ ITALIC_OFF: sgr(23),
87
+ UNDERLINE_OFF: sgr(24),
88
+ BLINK_OFF: sgr(25),
89
+ PROPORTIONAL: sgr(26), // Proportional spacing (rare)
90
+ INVERSE_OFF: sgr(27),
91
+ REVEAL: sgr(28), // Conceal off
92
+ STRIKE_OFF: sgr(29),
93
+ // 30-37: standard fg (see Color)
94
+ // 38: extended fg
95
+ // 39: default fg
96
+ // 40-47: standard bg (see Color)
97
+ // 48: extended bg
98
+ // 49: default bg
99
+ PROPORTIONAL_OFF: sgr(50),
100
+ FRAMED: sgr(51),
101
+ ENCIRCLED: sgr(52),
102
+ OVERLINE: sgr(53),
103
+ FRAMED_OFF: sgr(54), // Framed + encircled off
104
+ OVERLINE_OFF: sgr(55),
105
+ // 58: underline color (extended)
106
+ // 59: default underline color
107
+ SUPERSCRIPT: sgr(73), // Rare; mintty etc.
108
+ SUBSCRIPT: sgr(74),
109
+ SUPERSCRIPT_OFF:sgr(75),
110
+ DOUBLE_UNDERLINE: sgr(21), // In some terminals = double underline
111
+ };
112
+
113
+ // ── Standard 16 colors ───────────────────────────────────────
114
+
115
+ const Color = {
116
+ // Foreground
117
+ FG_BLACK: sgr(30),
118
+ FG_RED: sgr(31),
119
+ FG_GREEN: sgr(32),
120
+ FG_YELLOW: sgr(33),
121
+ FG_BLUE: sgr(34),
122
+ FG_MAGENTA: sgr(35),
123
+ FG_CYAN: sgr(36),
124
+ FG_WHITE: sgr(37),
125
+ FG_DEFAULT: sgr(39),
126
+ FG_BRIGHT_BLACK: sgr(90), // "Gray" / dark gray
127
+ FG_BRIGHT_RED: sgr(91),
128
+ FG_BRIGHT_GREEN: sgr(92),
129
+ FG_BRIGHT_YELLOW: sgr(93),
130
+ FG_BRIGHT_BLUE: sgr(94),
131
+ FG_BRIGHT_MAGENTA: sgr(95),
132
+ FG_BRIGHT_CYAN: sgr(96),
133
+ FG_BRIGHT_WHITE: sgr(97),
134
+
135
+ // Background
136
+ BG_BLACK: sgr(40),
137
+ BG_RED: sgr(41),
138
+ BG_GREEN: sgr(42),
139
+ BG_YELLOW: sgr(43),
140
+ BG_BLUE: sgr(44),
141
+ BG_MAGENTA: sgr(45),
142
+ BG_CYAN: sgr(46),
143
+ BG_WHITE: sgr(47),
144
+ BG_DEFAULT: sgr(49),
145
+ BG_BRIGHT_BLACK: sgr(100),
146
+ BG_BRIGHT_RED: sgr(101),
147
+ BG_BRIGHT_GREEN: sgr(102),
148
+ BG_BRIGHT_YELLOW: sgr(103),
149
+ BG_BRIGHT_BLUE: sgr(104),
150
+ BG_BRIGHT_MAGENTA: sgr(105),
151
+ BG_BRIGHT_CYAN: sgr(106),
152
+ BG_BRIGHT_WHITE: sgr(107),
153
+ };
154
+
155
+ // ── 256-color ─────────────────────────────────────────────────
156
+
157
+ /**
158
+ * Set foreground to a 256-color palette entry (0–255).
159
+ * @param {number} n
160
+ * @returns {string}
161
+ */
162
+ function fg256(n) { return sgr(38, 5, n); }
163
+
164
+ /**
165
+ * Set background to a 256-color palette entry (0–255).
166
+ * @param {number} n
167
+ * @returns {string}
168
+ */
169
+ function bg256(n) { return sgr(48, 5, n); }
170
+
171
+ /**
172
+ * Set underline color to a 256-color palette entry.
173
+ * @param {number} n
174
+ * @returns {string}
175
+ */
176
+ function ul256(n) { return sgr(58, 5, n); }
177
+
178
+ // ── True color (24-bit RGB) ───────────────────────────────────
179
+
180
+ /**
181
+ * Set foreground to an RGB true color.
182
+ * @param {number} r 0–255
183
+ * @param {number} g 0–255
184
+ * @param {number} b 0–255
185
+ * @returns {string}
186
+ */
187
+ function fgRGB(r, g, b) { return sgr(38, 2, r, g, b); }
188
+
189
+ /**
190
+ * Set background to an RGB true color.
191
+ */
192
+ function bgRGB(r, g, b) { return sgr(48, 2, r, g, b); }
193
+
194
+ /**
195
+ * Set underline color to an RGB true color.
196
+ */
197
+ function ulRGB(r, g, b) { return sgr(58, 2, r, g, b); }
198
+
199
+ /**
200
+ * Parse a hex color string (#RGB or #RRGGBB) to [r, g, b].
201
+ * @param {string} hex
202
+ * @returns {[number, number, number]}
203
+ */
204
+ function _hexToRGB(hex) {
205
+ hex = hex.replace('#', '');
206
+ if (hex.length === 3) hex = hex.split('').map(c => c + c).join('');
207
+ return [
208
+ parseInt(hex.slice(0, 2), 16),
209
+ parseInt(hex.slice(2, 4), 16),
210
+ parseInt(hex.slice(4, 6), 16),
211
+ ];
212
+ }
213
+
214
+ /**
215
+ * Set foreground to a hex color.
216
+ * @param {string} hex '#RRGGBB' or '#RGB'
217
+ * @returns {string}
218
+ */
219
+ function fgHex(hex) { return fgRGB(..._hexToRGB(hex)); }
220
+
221
+ /**
222
+ * Set background to a hex color.
223
+ */
224
+ function bgHex(hex) { return bgRGB(..._hexToRGB(hex)); }
225
+
226
+ /**
227
+ * Set underline color to a hex color.
228
+ */
229
+ function ulHex(hex) { return ulRGB(..._hexToRGB(hex)); }
230
+
231
+ // ── Underline style (kitty / VTE extension) ──────────────────
232
+
233
+ const UnderlineStyle = {
234
+ OFF: sgr(4, 0), // No underline
235
+ SINGLE: sgr(4, 1), // Single underline (or just sgr(4))
236
+ DOUBLE: sgr(4, 2), // Double underline
237
+ CURLY: sgr(4, 3), // Curly / wavy underline
238
+ DOTTED: sgr(4, 4), // Dotted underline
239
+ DASHED: sgr(4, 5), // Dashed underline
240
+ };
241
+
242
+ // ── Composite: wrap a string with open/close SGR codes ────────
243
+
244
+ /**
245
+ * Wrap a string with one or more SGR open codes, closing with RESET.
246
+ * @param {string} str
247
+ * @param {...number} codes SGR numeric codes
248
+ * @returns {string}
249
+ */
250
+ function wrap(str, ...codes) {
251
+ return sgr(...codes) + str + RESET;
252
+ }
253
+
254
+ /**
255
+ * Wrap a string with explicit open and close SGR sequences.
256
+ * @param {string} str
257
+ * @param {string} open - full escape sequence to prepend
258
+ * @param {string} close - full escape sequence to append
259
+ * @returns {string}
260
+ */
261
+ function wrapRaw(str, open, close) {
262
+ return open + str + close;
263
+ }
264
+
265
+ // ────────────────────────────────────────────────────────────
266
+ // SECTION 3: CURSOR CONTROL
267
+ // ────────────────────────────────────────────────────────────
268
+
269
+ const Cursor = {
270
+ // ── Absolute positioning ─────────────────────────────────
271
+
272
+ /** Move cursor to row, col (1-based). */
273
+ to: (row, col) => csi(`${row};${col}H`),
274
+ /** Alias: CUP — Cursor Position. */
275
+ pos: (row, col) => csi(`${row};${col}H`),
276
+ /** Move to column (1-based). */
277
+ toCol: (col) => csi(`${col}G`),
278
+ /** Move to row (1-based). */
279
+ toRow: (row) => csi(`${row}d`),
280
+
281
+ // ── Relative movement ────────────────────────────────────
282
+
283
+ /** Move up N lines. */
284
+ up: (n = 1) => csi(`${n}A`),
285
+ /** Move down N lines. */
286
+ down: (n = 1) => csi(`${n}B`),
287
+ /** Move right N columns. */
288
+ right: (n = 1) => csi(`${n}C`),
289
+ /** Move left N columns. */
290
+ left: (n = 1) => csi(`${n}D`),
291
+ /** Move down N lines, to column 1 (CNL). */
292
+ nextLine: (n = 1) => csi(`${n}E`),
293
+ /** Move up N lines, to column 1 (CPL). */
294
+ prevLine: (n = 1) => csi(`${n}F`),
295
+
296
+ // ── Save / Restore ───────────────────────────────────────
297
+
298
+ /** Save cursor position (ANSI/VT100). */
299
+ save: ESC + '7',
300
+ /** Restore cursor position (ANSI/VT100). */
301
+ restore: ESC + '8',
302
+ /** Save cursor position (CSI variant). */
303
+ saveCSI: csi('s'),
304
+ /** Restore cursor position (CSI variant). */
305
+ restoreCSI: csi('u'),
306
+ /** Save cursor + attrs (DECSC). */
307
+ saveDEC: ESC + '7',
308
+ /** Restore cursor + attrs (DECRC). */
309
+ restoreDEC: ESC + '8',
310
+
311
+ // ── Visibility ───────────────────────────────────────────
312
+
313
+ /** Hide cursor. */
314
+ hide: csi('?25l'),
315
+ /** Show cursor. */
316
+ show: csi('?25h'),
317
+
318
+ // ── Style (DECSCUSR) ─────────────────────────────────────
319
+
320
+ /** Cursor styles via DECSCUSR. */
321
+ style: {
322
+ DEFAULT: csi('0 q'),
323
+ BLOCK_BLINK: csi('1 q'),
324
+ BLOCK_STEADY: csi('2 q'),
325
+ UNDERLINE_BLINK: csi('3 q'),
326
+ UNDERLINE_STEADY: csi('4 q'),
327
+ BAR_BLINK: csi('5 q'),
328
+ BAR_STEADY: csi('6 q'),
329
+ },
330
+
331
+ // ── Blinking ─────────────────────────────────────────────
332
+
333
+ /** Enable cursor blinking. */
334
+ blinkOn: csi('?12h'),
335
+ /** Disable cursor blinking. */
336
+ blinkOff: csi('?12l'),
337
+
338
+ // ── Report ───────────────────────────────────────────────
339
+
340
+ /** Request cursor position report (CPR). Terminal replies with ESC[row;colR. */
341
+ report: csi('6n'),
342
+ /** Request extended cursor position (DECXCPR). */
343
+ reportExt: csi('?6n'),
344
+ };
345
+
346
+ // ────────────────────────────────────────────────────────────
347
+ // SECTION 4: SCREEN / LINE ERASING
348
+ // ────────────────────────────────────────────────────────────
349
+
350
+ const Erase = {
351
+ // ── Display ──────────────────────────────────────────────
352
+
353
+ /** Erase from cursor to end of screen (ED 0). */
354
+ toEndOfScreen: csi('0J'),
355
+ /** Erase from start of screen to cursor (ED 1). */
356
+ toStartOfScreen: csi('1J'),
357
+ /** Erase entire screen (ED 2). */
358
+ screen: csi('2J'),
359
+ /** Erase entire screen + scrollback buffer (ED 3, xterm). */
360
+ screenAndScrollback:csi('3J'),
361
+
362
+ // ── Line ─────────────────────────────────────────────────
363
+
364
+ /** Erase from cursor to end of line (EL 0). */
365
+ toEndOfLine: csi('0K'),
366
+ /** Erase from start of line to cursor (EL 1). */
367
+ toStartOfLine: csi('1K'),
368
+ /** Erase entire current line (EL 2). */
369
+ line: csi('2K'),
370
+
371
+ // ── Characters ───────────────────────────────────────────
372
+
373
+ /** Erase N characters at cursor position (ECH). */
374
+ chars: (n = 1) => csi(`${n}X`),
375
+ /** Delete N characters from cursor (DCH, shifts left). */
376
+ deleteChars: (n = 1) => csi(`${n}P`),
377
+ /** Delete N lines from cursor (DL, shifts up). */
378
+ deleteLines: (n = 1) => csi(`${n}M`),
379
+
380
+ // ── Insert ───────────────────────────────────────────────
381
+
382
+ /** Insert N blank characters at cursor (ICH, shifts right). */
383
+ insertChars: (n = 1) => csi(`${n}@`),
384
+ /** Insert N blank lines at cursor (IL, shifts down). */
385
+ insertLines: (n = 1) => csi(`${n}L`),
386
+ };
387
+
388
+ // ────────────────────────────────────────────────────────────
389
+ // SECTION 5: SCROLLING
390
+ // ────────────────────────────────────────────────────────────
391
+
392
+ const Scroll = {
393
+ /** Scroll up N lines (SU — new lines at bottom). */
394
+ up: (n = 1) => csi(`${n}S`),
395
+ /** Scroll down N lines (SD — new lines at top). */
396
+ down: (n = 1) => csi(`${n}T`),
397
+ /** Set scrolling region top/bottom rows (DECSTBM, 1-based). */
398
+ region: (top, bottom) => csi(`${top};${bottom}r`),
399
+ /** Reset scrolling region to full screen. */
400
+ resetRegion: csi('r'),
401
+ /** Enable smooth (slow) scroll. */
402
+ smoothOn: csi('?4h'),
403
+ /** Disable smooth scroll (jump scroll). */
404
+ smoothOff: csi('?4l'),
405
+ /** Save scrolling region. */
406
+ save: ESC + '7',
407
+ /** Restore scrolling region. */
408
+ restore: ESC + '8',
409
+ /** Pan down (DECBI — Back Index). */
410
+ panDown: ESC + '6',
411
+ /** Pan up (DECFI — Forward Index). */
412
+ panUp: ESC + '9',
413
+ };
414
+
415
+ // ────────────────────────────────────────────────────────────
416
+ // SECTION 6: SCREEN MODES & ALTERNATE BUFFER
417
+ // ────────────────────────────────────────────────────────────
418
+
419
+ const Screen = {
420
+ // ── Alternate screen buffer ──────────────────────────────
421
+
422
+ /** Enter alternate screen buffer (xterm). */
423
+ altOn: csi('?1049h'),
424
+ /** Leave alternate screen buffer. */
425
+ altOff: csi('?1049l'),
426
+ /** Enter alternate screen (simple, no save/restore). */
427
+ altSimpleOn: csi('?47h'),
428
+ /** Leave alternate screen (simple). */
429
+ altSimpleOff: csi('?47l'),
430
+
431
+ // ── Screen modes ─────────────────────────────────────────
432
+
433
+ /** 40×25 monochrome (text). */
434
+ mode40x25Mono: csi('=0h'),
435
+ /** 40×25 color. */
436
+ mode40x25Color: csi('=1h'),
437
+ /** 80×25 monochrome. */
438
+ mode80x25Mono: csi('=2h'),
439
+ /** 80×25 color. */
440
+ mode80x25Color: csi('=3h'),
441
+ /** 320×200 4-color. */
442
+ mode320x200_4: csi('=4h'),
443
+ /** 320×200 monochrome. */
444
+ mode320x200Mono:csi('=5h'),
445
+ /** 320×200 color (mode 13h). */
446
+ mode320x200_256:csi('=13h'),
447
+ /** 640×200 monochrome. */
448
+ mode640x200Mono:csi('=6h'),
449
+ /** 640×200 color. */
450
+ mode640x200Color:csi('=14h'),
451
+ /** Line wrap on. */
452
+ wrapOn: csi('?7h'),
453
+ /** Line wrap off. */
454
+ wrapOff: csi('?7l'),
455
+ /** Reverse video (light background). */
456
+ reverseOn: csi('?5h'),
457
+ /** Normal video. */
458
+ reverseOff: csi('?5l'),
459
+ /** Enable bracketed paste mode. */
460
+ bracketedPasteOn: csi('?2004h'),
461
+ /** Disable bracketed paste mode. */
462
+ bracketedPasteOff: csi('?2004l'),
463
+ /** Enable focus reporting. */
464
+ focusReportOn: csi('?1004h'),
465
+ /** Disable focus reporting. */
466
+ focusReportOff: csi('?1004l'),
467
+
468
+ // ── Resize ────────────────────────────────────────────────
469
+
470
+ /** Resize terminal to cols×rows (xterm CSI 8 ; rows ; cols t). */
471
+ resize: (rows, cols) => csi(`8;${rows};${cols}t`),
472
+ /** Maximize window. */
473
+ maximize: csi('9;1t'),
474
+ /** Restore window size. */
475
+ restoreSize: csi('9;0t'),
476
+ /** Raise window to front. */
477
+ raise: csi('5t'),
478
+ /** Lower window. */
479
+ lower: csi('6t'),
480
+ /** Refresh / repaint window. */
481
+ repaint: csi('7t'),
482
+ /** Report terminal size in chars (CSI 18 t). */
483
+ reportSize: csi('18t'),
484
+ /** Report screen size in chars (CSI 19 t). */
485
+ reportScreenSize: csi('19t'),
486
+ };
487
+
488
+ // ────────────────────────────────────────────────────────────
489
+ // SECTION 7: MOUSE REPORTING
490
+ // ────────────────────────────────────────────────────────────
491
+
492
+ const Mouse = {
493
+ // ── Basic mouse ──────────────────────────────────────────
494
+
495
+ /** Enable X10 mouse (button press only). */
496
+ x10On: csi('?9h'),
497
+ x10Off: csi('?9l'),
498
+
499
+ /** Enable normal (VT200) mouse reporting (press+release). */
500
+ normalOn: csi('?1000h'),
501
+ normalOff: csi('?1000l'),
502
+
503
+ /** Enable mouse highlight tracking. */
504
+ highlightOn: csi('?1001h'),
505
+ highlightOff: csi('?1001l'),
506
+
507
+ /** Enable button-event mouse reporting. */
508
+ buttonOn: csi('?1002h'),
509
+ buttonOff: csi('?1002l'),
510
+
511
+ /** Enable any-event mouse reporting (motion too). */
512
+ anyOn: csi('?1003h'),
513
+ anyOff: csi('?1003l'),
514
+
515
+ // ── Extended encoding ────────────────────────────────────
516
+
517
+ /** UTF-8 extended mouse mode (xterm). */
518
+ utf8On: csi('?1005h'),
519
+ utf8Off: csi('?1005l'),
520
+
521
+ /** SGR extended mouse mode (recommended; supports >223 cols). */
522
+ sgrOn: csi('?1006h'),
523
+ sgrOff: csi('?1006l'),
524
+
525
+ /** URXVT extended mouse mode. */
526
+ urxvtOn: csi('?1015h'),
527
+ urxvtOff: csi('?1015l'),
528
+
529
+ /** SGR pixel-based mouse reporting (xterm 379+). */
530
+ sgrPixelOn: csi('?1016h'),
531
+ sgrPixelOff: csi('?1016l'),
532
+
533
+ // ── Convenience combos ───────────────────────────────────
534
+
535
+ /** Enable full mouse (any-event + SGR encoding). */
536
+ enableFull: csi('?1003h') + csi('?1006h'),
537
+ /** Disable full mouse. */
538
+ disableFull: csi('?1003l') + csi('?1006l'),
539
+ };
540
+
541
+ // ────────────────────────────────────────────────────────────
542
+ // SECTION 8: WINDOW / TITLE (OSC)
543
+ // ────────────────────────────────────────────────────────────
544
+
545
+ const Window = {
546
+ /**
547
+ * Set window title.
548
+ * @param {string} title
549
+ * @returns {string}
550
+ */
551
+ title: (title) => osc(`0;${title}`),
552
+ /**
553
+ * Set icon name only.
554
+ */
555
+ iconName: (name) => osc(`1;${name}`),
556
+ /**
557
+ * Set both icon name and window title.
558
+ */
559
+ titleAndIcon: (title) => osc(`0;${title}`),
560
+ /**
561
+ * Set terminal tab color (iTerm2 / some terminals). Hex e.g. 'ff0000'.
562
+ */
563
+ tabColor: (hex) => osc(`6;1;bg;red;brightness;${parseInt(hex.slice(0,2),16)}`),
564
+ /**
565
+ * iTerm2: set current directory.
566
+ */
567
+ currentDir:(path) => osc(`7;file://localhost${path}`),
568
+ /**
569
+ * iTerm2: set mark (shell integration).
570
+ */
571
+ mark: osc('133;A'),
572
+ /**
573
+ * iTerm2: start of command output.
574
+ */
575
+ cmdStart: osc('133;C'),
576
+ /**
577
+ * iTerm2: end of command output.
578
+ */
579
+ cmdEnd: (code=0) => osc(`133;D;${code}`),
580
+ /**
581
+ * Hyperlink (OSC 8). Opens url, closes with empty url.
582
+ * @param {string} url
583
+ * @param {string} text
584
+ * @returns {string}
585
+ */
586
+ hyperlink: (url, text) => osc(`8;;${url}`) + ST + text + osc('8;;') + ST,
587
+ /**
588
+ * Notify (libnotify via OSC 777, supported by some terminals).
589
+ */
590
+ notify: (title, body) => osc(`777;notify;${title};${body}`),
591
+ /**
592
+ * Set clipboard contents (OSC 52).
593
+ * @param {string} data - base64-encoded string
594
+ * @param {'c'|'p'|'s'} [buf='c'] - c=clipboard, p=primary, s=secondary
595
+ */
596
+ clipboard: (data, buf = 'c') => osc(`52;${buf};${data}`),
597
+ };
598
+
599
+ // ────────────────────────────────────────────────────────────
600
+ // SECTION 9: DEVICE CONTROL / TERMINAL QUERIES
601
+ // ────────────────────────────────────────────────────────────
602
+
603
+ const Device = {
604
+ /** Device Attributes (DA1) — request terminal ID. */
605
+ queryDA1: csi('c'),
606
+ /** Secondary Device Attributes (DA2). */
607
+ queryDA2: csi('>c'),
608
+ /** Tertiary Device Attributes (DA3). */
609
+ queryDA3: csi('=c'),
610
+ /** Status report (DSR) — reports cursor position. */
611
+ statusReport: csi('5n'),
612
+ /** DECID — identify terminal. */
613
+ identify: ESC + 'Z',
614
+ /** Request DEC private mode (DECRQM). */
615
+ queryMode: (mode) => csi(`?${mode}$p`),
616
+ /** Soft terminal reset (DECSTR). */
617
+ softReset: csi('!p'),
618
+ /** Hard terminal reset (RIS). */
619
+ hardReset: ESC + 'c',
620
+ /** Invoke character set G0 (SI). */
621
+ charSetG0: '\x0F',
622
+ /** Invoke character set G1 (SO). */
623
+ charSetG1: '\x0E',
624
+ /** Designate G0 as US ASCII. */
625
+ g0ASCII: ESC + '(B',
626
+ /** Designate G0 as DEC special graphics. */
627
+ g0DEC: ESC + '(0',
628
+ /** Conformance Level. */
629
+ conformLevel1: csi('61"p'),
630
+ conformLevel2: csi('62"p'),
631
+ conformLevel3: csi('63"p'),
632
+ conformLevel4: csi('64"p'),
633
+ /** XTVERSION — request terminal version string. */
634
+ queryVersion: csi('>0q'),
635
+ /** XTSMGRAPHICS — sixel / ReGIS graphics queries. */
636
+ querySixel: csi('?1;1;0S'),
637
+ };
638
+
639
+ // ────────────────────────────────────────────────────────────
640
+ // SECTION 10: SPECIAL / MISC SEQUENCES
641
+ // ────────────────────────────────────────────────────────────
642
+
643
+ const Special = {
644
+ /** Bell (BEL). */
645
+ bell: BEL,
646
+ /** Backspace. */
647
+ backspace: '\x08',
648
+ /** Horizontal tab. */
649
+ tab: '\x09',
650
+ /** Line feed. */
651
+ lf: '\x0A',
652
+ /** Vertical tab. */
653
+ vt: '\x0B',
654
+ /** Form feed / new page. */
655
+ ff: '\x0C',
656
+ /** Carriage return. */
657
+ cr: '\x0D',
658
+ /** Return to home position (no erase). */
659
+ home: csi('H'),
660
+ /** Next line (NEL). */
661
+ nextLine: ESC + 'E',
662
+ /** Index (IND) — move down one line. */
663
+ index: ESC + 'D',
664
+ /** Reverse index (RI) — move up one line. */
665
+ reverseIndex: ESC + 'M',
666
+ /** Tab set at current column (HTS). */
667
+ tabSet: ESC + 'H',
668
+ /** Tab clear at current column (TBC 0). */
669
+ tabClear: csi('0g'),
670
+ /** Tab clear all (TBC 3). */
671
+ tabClearAll: csi('3g'),
672
+ /** Tab forward N (CHT). */
673
+ tabForward: (n=1) => csi(`${n}I`),
674
+ /** Tab backward N (CBT). */
675
+ tabBackward: (n=1) => csi(`${n}Z`),
676
+ /** Lock keyboard (DECLL). */
677
+ lockKbd: csi('0q'),
678
+ /** Unlock keyboard. */
679
+ unlockKbd: csi('2q'),
680
+ /** Application Keypad Mode. */
681
+ keypadApp: ESC + '=',
682
+ /** Numeric Keypad Mode. */
683
+ keypadNum: ESC + '>',
684
+ /** Application Cursor Keys (DECCKM). */
685
+ cursorKeysApp: csi('?1h'),
686
+ /** Normal Cursor Keys. */
687
+ cursorKeysNormal: csi('?1l'),
688
+ /** Enable auto-repeat. */
689
+ autoRepeatOn: csi('?8h'),
690
+ /** Disable auto-repeat. */
691
+ autoRepeatOff: csi('?8l'),
692
+ /** Set insert mode (IRM). */
693
+ insertModeOn: csi('4h'),
694
+ /** Set replace mode. */
695
+ insertModeOff: csi('4l'),
696
+ /** Enable local echo. */
697
+ echoOn: csi('12l'),
698
+ /** Disable local echo. */
699
+ echoOff: csi('12h'),
700
+ /** DEC Origin Mode on (DECOM). */
701
+ originModeOn: csi('?6h'),
702
+ /** DEC Origin Mode off. */
703
+ originModeOff: csi('?6l'),
704
+ /** Column 132 mode on (DECCOLM). */
705
+ col132On: csi('?3h'),
706
+ /** Column 80 mode. */
707
+ col80On: csi('?3l'),
708
+ /** Enable 80/132 column switching (DECCOLM allowed). */
709
+ colSwitchOn: csi('?40h'),
710
+ colSwitchOff: csi('?40l'),
711
+ /** Left/right margin mode (DECLRMM). */
712
+ lrMarginOn: csi('?69h'),
713
+ lrMarginOff: csi('?69l'),
714
+ /** Set left and right margins (DECSLRM). */
715
+ setLRMargins: (l, r) => csi(`${l};${r}s`),
716
+ /** Print screen. */
717
+ printScreen: csi('i'),
718
+ /** Print line. */
719
+ printLine: csi('1i'),
720
+ /** Enter print controller mode. */
721
+ printCtrlOn: csi('5i'),
722
+ /** Exit print controller mode. */
723
+ printCtrlOff: csi('4i'),
724
+ };
725
+
726
+ // ────────────────────────────────────────────────────────────
727
+ // SECTION 11: SIXEL GRAPHICS (DCS)
728
+ // ────────────────────────────────────────────────────────────
729
+
730
+ const Sixel = {
731
+ /**
732
+ * Begin a sixel data stream.
733
+ * @param {number} [aspectRatio=0] - 0=1:1 pixels, 2=2:1 etc.
734
+ * @param {number} [background=0] - 0=bg stays, 1=bg clears to first color
735
+ * @param {number} [gridSize=0] - 0=use terminal default
736
+ * @returns {string}
737
+ */
738
+ begin: (aspectRatio = 0, background = 0, gridSize = 0) =>
739
+ `${DCS}${aspectRatio};${background};${gridSize}q`,
740
+
741
+ /** End sixel data stream. */
742
+ end: ST,
743
+
744
+ /** Wrap raw sixel data in a DCS container. */
745
+ wrap: (data, aspectRatio = 0, background = 0) =>
746
+ `${DCS}${aspectRatio};${background};0q${data}${ST}`,
747
+
748
+ /**
749
+ * Set sixel color register (# n ; 2 ; r ; g ; b for RGB, # n ; 1 ; h ; l ; s for HLS).
750
+ * @param {number} reg - register index 0–255
751
+ * @param {number} r - red 0–100
752
+ * @param {number} g - green 0–100
753
+ * @param {number} b - blue 0–100
754
+ */
755
+ colorRGB: (reg, r, g, b) => `#${reg};2;${r};${g};${b}`,
756
+
757
+ /**
758
+ * Set sixel color register (HLS).
759
+ * @param {number} reg
760
+ * @param {number} h hue 0–360
761
+ * @param {number} l lightness 0–100
762
+ * @param {number} s saturation 0–100
763
+ */
764
+ colorHLS: (reg, h, l, s) => `#${reg};1;${h};${l};${s}`,
765
+
766
+ /** Use a defined color register for following sixel data. */
767
+ useColor: (reg) => `#${reg}`,
768
+ };
769
+
770
+ // ────────────────────────────────────────────────────────────
771
+ // SECTION 12: KITTY GRAPHICS PROTOCOL (APC)
772
+ // ────────────────────────────────────────────────────────────
773
+
774
+ /**
775
+ * Build a kitty graphics protocol APC payload.
776
+ * @param {object} keys - key=value control pairs
777
+ * @param {string} [payload='']
778
+ * @returns {string}
779
+ */
780
+ function kittyGfx(keys, payload = '') {
781
+ const ctrl = Object.entries(keys).map(([k, v]) => `${k}=${v}`).join(',');
782
+ return `${APC}G${ctrl};${payload}${ST}`;
783
+ }
784
+
785
+ const KittyGfx = {
786
+ /**
787
+ * Transmit image data (chunked base64).
788
+ * @param {string} b64data - base64 payload chunk
789
+ * @param {object} [opts]
790
+ * @param {'png'|'rgb'|'rgba'|'jpg'} [opts.format='png']
791
+ * @param {number} [opts.width]
792
+ * @param {number} [opts.height]
793
+ * @param {number} [opts.id] - image id
794
+ * @param {0|1} [opts.more=0] - 1 if more chunks follow
795
+ */
796
+ transmit: (b64data, opts = {}) => {
797
+ const keys = { a: 't', f: opts.format === 'rgb' ? 24 : opts.format === 'rgba' ? 32 : opts.format === 'jpg' ? 100 : 100, t: 'd' };
798
+ if (opts.width) keys.s = opts.width;
799
+ if (opts.height) keys.v = opts.height;
800
+ if (opts.id) keys.i = opts.id;
801
+ if (opts.more) keys.m = opts.more;
802
+ return kittyGfx(keys, b64data);
803
+ },
804
+
805
+ /**
806
+ * Display a previously transmitted image.
807
+ * @param {number} id
808
+ * @param {object} [opts]
809
+ * @param {number} [opts.x] - display column
810
+ * @param {number} [opts.y] - display row
811
+ * @param {number} [opts.cols] - display columns
812
+ * @param {number} [opts.rows] - display rows
813
+ */
814
+ display: (id, opts = {}) => {
815
+ const keys = { a: 'p', i: id };
816
+ if (opts.x !== undefined) keys.X = opts.x;
817
+ if (opts.y !== undefined) keys.Y = opts.y;
818
+ if (opts.cols !== undefined) keys.c = opts.cols;
819
+ if (opts.rows !== undefined) keys.r = opts.rows;
820
+ return kittyGfx(keys);
821
+ },
822
+
823
+ /** Delete image by id. */
824
+ delete: (id) => kittyGfx({ a: 'd', d: 'i', i: id }),
825
+
826
+ /** Delete all images. */
827
+ deleteAll: kittyGfx({ a: 'd', d: 'a' }),
828
+ };
829
+
830
+ // ────────────────────────────────────────────────────────────
831
+ // SECTION 13: ITERM2 / WEZTERM INLINE IMAGES (OSC 1337)
832
+ // ────────────────────────────────────────────────────────────
833
+
834
+ const InlineImage = {
835
+ /**
836
+ * Display an inline image (iTerm2 / WezTerm protocol, OSC 1337).
837
+ * @param {string} b64data - base64-encoded image data
838
+ * @param {object} [opts]
839
+ * @param {string} [opts.name]
840
+ * @param {number} [opts.width] - in chars or pixels (e.g. '100px' or 10)
841
+ * @param {number} [opts.height]
842
+ * @param {boolean} [opts.preserveAspect=true]
843
+ * @param {boolean} [opts.inline=true]
844
+ */
845
+ display: (b64data, opts = {}) => {
846
+ const args = [`size=${b64data.length}`];
847
+ if (opts.name) args.push(`name=${Buffer.from ? Buffer.from(opts.name).toString('base64') : btoa(opts.name)}`);
848
+ if (opts.width) args.push(`width=${opts.width}`);
849
+ if (opts.height) args.push(`height=${opts.height}`);
850
+ args.push(`preserveAspectRatio=${opts.preserveAspect === false ? 0 : 1}`);
851
+ args.push(`inline=${opts.inline === false ? 0 : 1}`);
852
+ return `${OSC}1337;File=${args.join(';')}:${b64data}${BEL}`;
853
+ },
854
+ };
855
+
856
+ // ────────────────────────────────────────────────────────────
857
+ // SECTION 14: STRIP / MEASURE / DETECT
858
+ // ────────────────────────────────────────────────────────────
859
+
860
+ /** Regex matching all ANSI escape sequences. */
861
+ const ANSI_RE = /\x1b(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~]|][^\x07\x1b]*(?:\x07|\x1b\\)|[()][AB012]|[NOPX^_][\s\S]*?\x1b\\)/g;
862
+
863
+ /**
864
+ * Strip all ANSI escape sequences from a string.
865
+ * @param {string} str
866
+ * @returns {string}
867
+ */
868
+ function strip(str) {
869
+ return str.replace(ANSI_RE, '');
870
+ }
871
+
872
+ /**
873
+ * Measure the visible (printable) length of a string after stripping ANSI.
874
+ * Accounts for fullwidth Unicode characters (CJK, emoji) as width 2.
875
+ * @param {string} str
876
+ * @returns {number}
877
+ */
878
+ function visibleLength(str) {
879
+ const s = strip(str);
880
+ let len = 0;
881
+ for (const cp of s) {
882
+ const code = cp.codePointAt(0);
883
+ // Fullwidth / wide chars: CJK unified, CJK compat, fullwidth forms, emoji blocks
884
+ if (
885
+ (code >= 0x1100 && code <= 0x115F) || // Hangul Jamo
886
+ (code >= 0x2E80 && code <= 0x303E) || // CJK Radicals
887
+ (code >= 0x3041 && code <= 0x33FF) || // Hiragana, Katakana, CJK compat
888
+ (code >= 0x3400 && code <= 0x4DBF) || // CJK Extension A
889
+ (code >= 0x4E00 && code <= 0xA4CF) || // CJK Unified
890
+ (code >= 0xA960 && code <= 0xA97F) || // Hangul Jamo Extended
891
+ (code >= 0xAC00 && code <= 0xD7FF) || // Hangul Syllables
892
+ (code >= 0xF900 && code <= 0xFAFF) || // CJK Compat Ideographs
893
+ (code >= 0xFE10 && code <= 0xFE19) || // Vertical Forms
894
+ (code >= 0xFE30 && code <= 0xFE4F) || // CJK Compat Forms
895
+ (code >= 0xFF01 && code <= 0xFF60) || // Fullwidth ASCII + Halfwidth Katakana
896
+ (code >= 0xFFE0 && code <= 0xFFE6) || // Fullwidth Signs
897
+ (code >= 0x1B000 && code <= 0x1B0FF) || // Kana Supplement
898
+ (code >= 0x1F004 && code <= 0x1F0CF) || // Mahjong / Playing cards
899
+ (code >= 0x1F300 && code <= 0x1F9FF) || // Misc symbols, Emoji
900
+ (code >= 0x20000 && code <= 0x2FFFD) || // CJK Extension B-F
901
+ (code >= 0x30000 && code <= 0x3FFFD) // CJK Extension G
902
+ ) {
903
+ len += 2;
904
+ } else if (code >= 0x0300 && code <= 0x036F) {
905
+ // Combining diacriticals: zero width
906
+ } else {
907
+ len += 1;
908
+ }
909
+ }
910
+ return len;
911
+ }
912
+
913
+ /**
914
+ * Detect whether the current environment likely supports ANSI color.
915
+ * @returns {'truecolor'|'256'|'16'|'none'}
916
+ */
917
+ function detectColorSupport() {
918
+ // Browser / non-Node environment
919
+ if (typeof process === 'undefined') return 'none';
920
+
921
+ const env = process.env || {};
922
+ const argv = process.argv || [];
923
+ const term = (env.TERM || '').toLowerCase();
924
+ const cterm = (env.COLORTERM || '').toLowerCase();
925
+
926
+ // Explicitly disabled
927
+ if (env.NO_COLOR !== undefined || env.NODE_DISABLE_COLORS !== undefined) return 'none';
928
+ if (argv.includes('--no-color') || argv.includes('--color=false')) return 'none';
929
+
930
+ // Force flags
931
+ if (argv.includes('--color=16m') || argv.includes('--color=full')) return 'truecolor';
932
+ if (argv.includes('--color=256')) return '256';
933
+ if (argv.includes('--color')) return '16';
934
+
935
+ // Truecolor env vars
936
+ if (cterm === 'truecolor' || cterm === '24bit') return 'truecolor';
937
+ if (env.TERM_PROGRAM === 'iTerm.app') return 'truecolor';
938
+ if (env.TERM_PROGRAM === 'hyper') return 'truecolor';
939
+ if (env.TERM_PROGRAM === 'vscode') return 'truecolor';
940
+ if (env.WT_SESSION) return 'truecolor'; // Windows Terminal
941
+ if (env.COLORTERM) return '256';
942
+
943
+ // 256 color
944
+ if (term.includes('256color')) return '256';
945
+ if (term.includes('256')) return '256';
946
+
947
+ // 16 color
948
+ if (term.includes('color') || term === 'xterm' || term === 'screen' || term === 'linux') return '16';
949
+
950
+ // Check if stdout is a TTY
951
+ if (process.stdout && process.stdout.isTTY) return '16';
952
+
953
+ return 'none';
954
+ }
955
+
956
+ /**
957
+ * Returns true if the environment supports at least basic color.
958
+ */
959
+ function hasColor() {
960
+ return detectColorSupport() !== 'none';
961
+ }
962
+
963
+ // ────────────────────────────────────────────────────────────
964
+ // SECTION 15: ANSI PARSER
965
+ // ────────────────────────────────────────────────────────────
966
+
967
+ /**
968
+ * @typedef {object} AnsiToken
969
+ * @property {'text'|'sgr'|'cursor'|'erase'|'osc'|'dcs'|'escape'|'unknown'} type
970
+ * @property {string} raw - the raw escape sequence or text chunk
971
+ * @property {string} [text] - for type='text', the plain text
972
+ * @property {number[]} [codes] - for type='sgr', the SGR code list
973
+ * @property {string} [cmd] - final byte / command identifier
974
+ * @property {string} [params] - raw parameter string
975
+ * @property {string} [payload] - for OSC/DCS, the payload string
976
+ * @property {object} [style] - decoded style object for SGR tokens
977
+ */
978
+
979
+ const SGR_NAMES = {
980
+ 0: 'reset',
981
+ 1: 'bold', 2: 'dim', 3: 'italic',
982
+ 4: 'underline', 5: 'blink', 6: 'blink_fast',
983
+ 7: 'inverse', 8: 'hidden', 9: 'strike',
984
+ 21: 'double_underline',
985
+ 22: 'normal', 23: 'italic_off', 24: 'underline_off',
986
+ 25: 'blink_off', 27: 'inverse_off', 28: 'reveal',
987
+ 29: 'strike_off',
988
+ 30: 'fg_black', 31: 'fg_red', 32: 'fg_green', 33: 'fg_yellow',
989
+ 34: 'fg_blue', 35: 'fg_magenta',36: 'fg_cyan', 37: 'fg_white',
990
+ 39: 'fg_default',
991
+ 40: 'bg_black', 41: 'bg_red', 42: 'bg_green', 43: 'bg_yellow',
992
+ 44: 'bg_blue', 45: 'bg_magenta',46: 'bg_cyan', 47: 'bg_white',
993
+ 49: 'bg_default',
994
+ 51: 'framed', 52: 'encircled', 53: 'overline',
995
+ 54: 'framed_off', 55: 'overline_off',
996
+ 90: 'fg_bright_black', 91: 'fg_bright_red', 92: 'fg_bright_green',
997
+ 93: 'fg_bright_yellow', 94: 'fg_bright_blue', 95: 'fg_bright_magenta',
998
+ 96: 'fg_bright_cyan', 97: 'fg_bright_white',
999
+ 100:'bg_bright_black', 101:'bg_bright_red', 102:'bg_bright_green',
1000
+ 103:'bg_bright_yellow', 104:'bg_bright_blue', 105:'bg_bright_magenta',
1001
+ 106:'bg_bright_cyan', 107:'bg_bright_white',
1002
+ };
1003
+
1004
+ /**
1005
+ * Decode a list of SGR codes into a human-readable style object.
1006
+ * @param {number[]} codes
1007
+ * @returns {object}
1008
+ */
1009
+ function decodeSGR(codes) {
1010
+ const style = {};
1011
+ let i = 0;
1012
+ while (i < codes.length) {
1013
+ const c = codes[i];
1014
+ if ((c === 38 || c === 48 || c === 58) && codes[i+1] === 2) {
1015
+ // RGB color
1016
+ const [r, g, b] = [codes[i+2], codes[i+3], codes[i+4]];
1017
+ const key = c === 38 ? 'fg' : c === 48 ? 'bg' : 'ul';
1018
+ style[key] = { type: 'rgb', r, g, b, hex: `#${[r,g,b].map(v=>v.toString(16).padStart(2,'0')).join('')}` };
1019
+ i += 5;
1020
+ } else if ((c === 38 || c === 48 || c === 58) && codes[i+1] === 5) {
1021
+ const key = c === 38 ? 'fg' : c === 48 ? 'bg' : 'ul';
1022
+ style[key] = { type: '256', index: codes[i+2] };
1023
+ i += 3;
1024
+ } else {
1025
+ if (SGR_NAMES[c]) style[SGR_NAMES[c]] = true;
1026
+ i++;
1027
+ }
1028
+ }
1029
+ return style;
1030
+ }
1031
+
1032
+ /**
1033
+ * Parse a string containing ANSI escape sequences into an array of tokens.
1034
+ * @param {string} str
1035
+ * @returns {AnsiToken[]}
1036
+ */
1037
+ function parse(str) {
1038
+ const tokens = [];
1039
+ // Tokeniser: match escape sequences or text runs
1040
+ const re = /\x1b(?:(\[)([\x30-\x3F]*)([\x20-\x2F]*)([\x40-\x7E])|(])((?:[^\x07\x1b]|\x1b(?!\\))*?)(?:\x07|\x1b\\)|(P)([\s\S]*?)\x1b\\|([@-Z\\-_]))/g;
1041
+ let last = 0;
1042
+
1043
+ for (let m = re.exec(str); m; m = re.exec(str)) {
1044
+ // Text before this match
1045
+ if (m.index > last) tokens.push({ type: 'text', raw: str.slice(last, m.index), text: str.slice(last, m.index) });
1046
+ last = re.lastIndex;
1047
+
1048
+ if (m[1] === '[') {
1049
+ // CSI sequence
1050
+ const params = m[2] || '';
1051
+ const inter = m[3] || '';
1052
+ const cmd = m[4];
1053
+ const raw = m[0];
1054
+ if (cmd === 'm') {
1055
+ // SGR
1056
+ const codes = params === '' ? [0] : params.split(';').map(Number);
1057
+ tokens.push({ type: 'sgr', raw, params, cmd, codes, style: decodeSGR(codes) });
1058
+ } else if ('ABCDEFGH'.includes(cmd)) {
1059
+ tokens.push({ type: 'cursor', raw, params, cmd });
1060
+ } else if ('JK'.includes(cmd)) {
1061
+ tokens.push({ type: 'erase', raw, params, cmd });
1062
+ } else {
1063
+ tokens.push({ type: 'csi', raw, params, inter, cmd });
1064
+ }
1065
+ } else if (m[5] === ']') {
1066
+ // OSC sequence
1067
+ tokens.push({ type: 'osc', raw: m[0], payload: m[6] });
1068
+ } else if (m[7] === 'P') {
1069
+ // DCS sequence
1070
+ tokens.push({ type: 'dcs', raw: m[0], payload: m[8] });
1071
+ } else {
1072
+ // Single ESC + char
1073
+ tokens.push({ type: 'escape', raw: m[0], cmd: m[9] });
1074
+ }
1075
+ }
1076
+
1077
+ // Trailing text
1078
+ if (last < str.length) tokens.push({ type: 'text', raw: str.slice(last), text: str.slice(last) });
1079
+ return tokens;
1080
+ }
1081
+
1082
+ // ────────────────────────────────────────────────────────────
1083
+ // SECTION 16: CHAINABLE ANSI STRING BUILDER
1084
+ // ────────────────────────────────────────────────────────────
1085
+
1086
+ /**
1087
+ * AnsiString — chainable ANSI-aware string builder.
1088
+ *
1089
+ * Every method returns a new AnsiString (immutable chain).
1090
+ * Call .toString() to get the final escape-code-embedded string.
1091
+ * Call .plain() to get the stripped visible text.
1092
+ *
1093
+ * @example
1094
+ * const s = AnsiString.of('Hello')
1095
+ * .bold()
1096
+ * .fgRGB(255, 100, 0)
1097
+ * .append(' World')
1098
+ * .underline()
1099
+ * .toString();
1100
+ */
1101
+ class AnsiString {
1102
+ /**
1103
+ * @param {string} [str='']
1104
+ */
1105
+ constructor(str = '') {
1106
+ this._buf = String(str);
1107
+ }
1108
+
1109
+ /** Create a new AnsiString from a value. */
1110
+ static of(str = '') { return new AnsiString(str); }
1111
+
1112
+ /** Get the raw (escape-code-embedded) string. */
1113
+ toString() { return this._buf; }
1114
+ valueOf() { return this._buf; }
1115
+
1116
+ /** Get the visible plain text (no escape codes). */
1117
+ plain() { return strip(this._buf); }
1118
+
1119
+ /** Visible character width. */
1120
+ width() { return visibleLength(this._buf); }
1121
+
1122
+ _clone(str) { return new AnsiString(str); }
1123
+
1124
+ // ── Append / prepend ────────────────────────────────────
1125
+
1126
+ /** Append raw text or another AnsiString. */
1127
+ append(str) { return this._clone(this._buf + String(str)); }
1128
+ /** Prepend raw text or another AnsiString. */
1129
+ prepend(str) { return this._clone(String(str) + this._buf); }
1130
+ /** Append a newline. */
1131
+ nl() { return this._clone(this._buf + '\n'); }
1132
+ /** Append a reset code. */
1133
+ reset() { return this._clone(this._buf + RESET); }
1134
+
1135
+ // ── SGR style methods ────────────────────────────────────
1136
+
1137
+ /** Apply one or more raw SGR codes to the current content. */
1138
+ _sgr(openCodes, closeCodes) {
1139
+ return this._clone(sgr(...openCodes) + this._buf + sgr(...closeCodes));
1140
+ }
1141
+
1142
+ bold() { return this._sgr([1], [22]); }
1143
+ dim() { return this._sgr([2], [22]); }
1144
+ italic() { return this._sgr([3], [23]); }
1145
+ underline() { return this._sgr([4], [24]); }
1146
+ blink() { return this._sgr([5], [25]); }
1147
+ blinkFast() { return this._sgr([6], [25]); }
1148
+ inverse() { return this._sgr([7], [27]); }
1149
+ hidden() { return this._sgr([8], [28]); }
1150
+ strike() { return this._sgr([9], [29]); }
1151
+ overline() { return this._sgr([53], [55]); }
1152
+ framed() { return this._sgr([51], [54]); }
1153
+ encircled() { return this._sgr([52], [54]); }
1154
+ doubleUnderline() { return this._sgr([21], [24]); }
1155
+ superscript() { return this._sgr([73], [75]); }
1156
+ subscript() { return this._sgr([74], [75]); }
1157
+
1158
+ // ── Standard 16 colors ───────────────────────────────────
1159
+
1160
+ black() { return this._sgr([30], [39]); }
1161
+ red() { return this._sgr([31], [39]); }
1162
+ green() { return this._sgr([32], [39]); }
1163
+ yellow() { return this._sgr([33], [39]); }
1164
+ blue() { return this._sgr([34], [39]); }
1165
+ magenta() { return this._sgr([35], [39]); }
1166
+ cyan() { return this._sgr([36], [39]); }
1167
+ white() { return this._sgr([37], [39]); }
1168
+ gray() { return this._sgr([90], [39]); }
1169
+ brightRed() { return this._sgr([91], [39]); }
1170
+ brightGreen() { return this._sgr([92], [39]); }
1171
+ brightYellow() { return this._sgr([93], [39]); }
1172
+ brightBlue() { return this._sgr([94], [39]); }
1173
+ brightMagenta() { return this._sgr([95], [39]); }
1174
+ brightCyan() { return this._sgr([96], [39]); }
1175
+ brightWhite() { return this._sgr([97], [39]); }
1176
+
1177
+ bgBlack() { return this._sgr([40], [49]); }
1178
+ bgRed() { return this._sgr([41], [49]); }
1179
+ bgGreen() { return this._sgr([42], [49]); }
1180
+ bgYellow() { return this._sgr([43], [49]); }
1181
+ bgBlue() { return this._sgr([44], [49]); }
1182
+ bgMagenta() { return this._sgr([45], [49]); }
1183
+ bgCyan() { return this._sgr([46], [49]); }
1184
+ bgWhite() { return this._sgr([47], [49]); }
1185
+ bgGray() { return this._sgr([100], [49]); }
1186
+ bgBrightRed() { return this._sgr([101], [49]); }
1187
+ bgBrightGreen() { return this._sgr([102], [49]); }
1188
+ bgBrightYellow() { return this._sgr([103], [49]); }
1189
+ bgBrightBlue() { return this._sgr([104], [49]); }
1190
+ bgBrightMagenta() { return this._sgr([105], [49]); }
1191
+ bgBrightCyan() { return this._sgr([106], [49]); }
1192
+ bgBrightWhite() { return this._sgr([107], [49]); }
1193
+
1194
+ // ── 256 color ────────────────────────────────────────────
1195
+
1196
+ /** Foreground 256-color (0–255). */
1197
+ fg256(n) { return this._clone(fg256(n) + this._buf + sgr(39)); }
1198
+ /** Background 256-color (0–255). */
1199
+ bg256(n) { return this._clone(bg256(n) + this._buf + sgr(49)); }
1200
+ /** Underline 256-color. */
1201
+ ul256(n) { return this._clone(ul256(n) + this._buf + sgr(59)); }
1202
+
1203
+ // ── True color ───────────────────────────────────────────
1204
+
1205
+ /** Foreground RGB. */
1206
+ fgRGB(r, g, b) { return this._clone(fgRGB(r,g,b) + this._buf + sgr(39)); }
1207
+ /** Background RGB. */
1208
+ bgRGB(r, g, b) { return this._clone(bgRGB(r,g,b) + this._buf + sgr(49)); }
1209
+ /** Underline RGB. */
1210
+ ulRGB(r, g, b) { return this._clone(ulRGB(r,g,b) + this._buf + sgr(59)); }
1211
+ /** Foreground hex. */
1212
+ fgHex(hex) { return this._clone(fgHex(hex) + this._buf + sgr(39)); }
1213
+ /** Background hex. */
1214
+ bgHex(hex) { return this._clone(bgHex(hex) + this._buf + sgr(49)); }
1215
+ /** Underline hex. */
1216
+ ulHex(hex) { return this._clone(ulHex(hex) + this._buf + sgr(59)); }
1217
+
1218
+ // ── Gradient (horizontal true-color) ─────────────────────
1219
+
1220
+ /**
1221
+ * Apply a horizontal RGB gradient across the visible characters.
1222
+ * @param {[number,number,number]} from - start [r,g,b]
1223
+ * @param {[number,number,number]} to - end [r,g,b]
1224
+ * @param {'fg'|'bg'} [target='fg']
1225
+ */
1226
+ gradient(from, to, target = 'fg') {
1227
+ const plain = this.plain();
1228
+ const len = plain.length || 1;
1229
+ let out = '';
1230
+ for (let i = 0; i < plain.length; i++) {
1231
+ const t = i / (len - 1 || 1);
1232
+ const r = Math.round(from[0] + (to[0] - from[0]) * t);
1233
+ const g = Math.round(from[1] + (to[1] - from[1]) * t);
1234
+ const b = Math.round(from[2] + (to[2] - from[2]) * t);
1235
+ out += (target === 'bg' ? bgRGB(r,g,b) : fgRGB(r,g,b)) + plain[i];
1236
+ }
1237
+ out += RESET;
1238
+ return this._clone(out);
1239
+ }
1240
+
1241
+ // ── Underline style ──────────────────────────────────────
1242
+
1243
+ curlyUnderline() { return this._clone(UnderlineStyle.CURLY + this._buf + sgr(24)); }
1244
+ dottedUnderline() { return this._clone(UnderlineStyle.DOTTED + this._buf + sgr(24)); }
1245
+ dashedUnderline() { return this._clone(UnderlineStyle.DASHED + this._buf + sgr(24)); }
1246
+
1247
+ // ── Wrapping helpers ─────────────────────────────────────
1248
+
1249
+ /** Wrap entire current buffer with open/close sequences. */
1250
+ wrap(open, close) { return this._clone(open + this._buf + close); }
1251
+
1252
+ /** Apply an arbitrary transform function to the raw string. */
1253
+ pipe(fn) { return this._clone(fn(this._buf)); }
1254
+
1255
+ /** Strip all ANSI codes. */
1256
+ strip() { return this._clone(strip(this._buf)); }
1257
+
1258
+ /** Pad right to a visible width (ANSI-aware). */
1259
+ padEnd(width, char = ' ') {
1260
+ const vlen = visibleLength(this._buf);
1261
+ if (vlen >= width) return this;
1262
+ return this._clone(this._buf + char.repeat(width - vlen));
1263
+ }
1264
+
1265
+ /** Pad left to a visible width (ANSI-aware). */
1266
+ padStart(width, char = ' ') {
1267
+ const vlen = visibleLength(this._buf);
1268
+ if (vlen >= width) return this;
1269
+ return this._clone(char.repeat(width - vlen) + this._buf);
1270
+ }
1271
+
1272
+ /** Center to a visible width (ANSI-aware). */
1273
+ padCenter(width, char = ' ') {
1274
+ const vlen = visibleLength(this._buf);
1275
+ if (vlen >= width) return this;
1276
+ const total = width - vlen;
1277
+ const left = Math.floor(total / 2);
1278
+ const right = total - left;
1279
+ return this._clone(char.repeat(left) + this._buf + char.repeat(right));
1280
+ }
1281
+
1282
+ /** Parse the current string into AnsiTokens. */
1283
+ parse() { return parse(this._buf); }
1284
+ }
1285
+
1286
+ // ────────────────────────────────────────────────────────────
1287
+ // SECTION 17: CONVENIENCE WRAP FUNCTIONS
1288
+ // ────────────────────────────────────────────────────────────
1289
+
1290
+ // These are standalone functions that mirror the AnsiString methods
1291
+ // for use without the class.
1292
+
1293
+ const bold = (s) => sgr(1) + s + sgr(22);
1294
+ const dim = (s) => sgr(2) + s + sgr(22);
1295
+ const italic = (s) => sgr(3) + s + sgr(23);
1296
+ const underline = (s) => sgr(4) + s + sgr(24);
1297
+ const blink = (s) => sgr(5) + s + sgr(25);
1298
+ const blinkFast = (s) => sgr(6) + s + sgr(25);
1299
+ const inverse = (s) => sgr(7) + s + sgr(27);
1300
+ const hidden = (s) => sgr(8) + s + sgr(28);
1301
+ const strike = (s) => sgr(9) + s + sgr(29);
1302
+ const overline = (s) => sgr(53) + s + sgr(55);
1303
+ const framed = (s) => sgr(51) + s + sgr(54);
1304
+
1305
+ // FG
1306
+ const black = (s) => sgr(30) + s + sgr(39);
1307
+ const red = (s) => sgr(31) + s + sgr(39);
1308
+ const green = (s) => sgr(32) + s + sgr(39);
1309
+ const yellow = (s) => sgr(33) + s + sgr(39);
1310
+ const blue = (s) => sgr(34) + s + sgr(39);
1311
+ const magenta = (s) => sgr(35) + s + sgr(39);
1312
+ const cyan = (s) => sgr(36) + s + sgr(39);
1313
+ const white = (s) => sgr(37) + s + sgr(39);
1314
+ const gray = (s) => sgr(90) + s + sgr(39);
1315
+ const brightRed = (s) => sgr(91) + s + sgr(39);
1316
+ const brightGreen = (s) => sgr(92) + s + sgr(39);
1317
+ const brightYellow = (s) => sgr(93) + s + sgr(39);
1318
+ const brightBlue = (s) => sgr(94) + s + sgr(39);
1319
+ const brightMagenta = (s) => sgr(95) + s + sgr(39);
1320
+ const brightCyan = (s) => sgr(96) + s + sgr(39);
1321
+ const brightWhite = (s) => sgr(97) + s + sgr(39);
1322
+
1323
+ // BG
1324
+ const bgBlack = (s) => sgr(40) + s + sgr(49);
1325
+ const bgRed = (s) => sgr(41) + s + sgr(49);
1326
+ const bgGreen = (s) => sgr(42) + s + sgr(49);
1327
+ const bgYellow = (s) => sgr(43) + s + sgr(49);
1328
+ const bgBlue = (s) => sgr(44) + s + sgr(49);
1329
+ const bgMagenta = (s) => sgr(45) + s + sgr(49);
1330
+ const bgCyan = (s) => sgr(46) + s + sgr(49);
1331
+ const bgWhite = (s) => sgr(47) + s + sgr(49);
1332
+ const bgGray = (s) => sgr(100) + s + sgr(49);
1333
+ const bgBrightRed = (s) => sgr(101) + s + sgr(49);
1334
+ const bgBrightGreen = (s) => sgr(102) + s + sgr(49);
1335
+ const bgBrightYellow = (s) => sgr(103) + s + sgr(49);
1336
+ const bgBrightBlue = (s) => sgr(104) + s + sgr(49);
1337
+ const bgBrightMagenta = (s) => sgr(105) + s + sgr(49);
1338
+ const bgBrightCyan = (s) => sgr(106) + s + sgr(49);
1339
+ const bgBrightWhite = (s) => sgr(107) + s + sgr(49);
1340
+
1341
+ /**
1342
+ * Apply a horizontal RGB gradient to a plain string.
1343
+ * @param {string} str
1344
+ * @param {[number,number,number]} from
1345
+ * @param {[number,number,number]} to
1346
+ * @param {'fg'|'bg'} [target='fg']
1347
+ */
1348
+ function gradient(str, from, to, target = 'fg') {
1349
+ return AnsiString.of(str).gradient(from, to, target).toString();
1350
+ }
1351
+
1352
+ // ────────────────────────────────────────────────────────────
1353
+ // EXPORTS
1354
+ // ────────────────────────────────────────────────────────────
1355
+
1356
+ module.exports = {
1357
+ kitdef: {
1358
+ // ── Primitives ──────────────────────────────────
1359
+ ESC, CSI, OSC, DCS, ST, BEL, SS3, PM, APC,
1360
+ csi, osc, oscST, sgr,
1361
+
1362
+ // ── SGR constants ────────────────────────────────
1363
+ RESET, RESET_FG, RESET_BG, RESET_UNDER,
1364
+ Style, Color, UnderlineStyle,
1365
+
1366
+ // ── Color functions ──────────────────────────────
1367
+ fg256, bg256, ul256,
1368
+ fgRGB, bgRGB, ulRGB,
1369
+ fgHex, bgHex, ulHex,
1370
+
1371
+ // ── Wrap helpers ─────────────────────────────────
1372
+ wrap, wrapRaw,
1373
+
1374
+ // ── Standalone style functions ───────────────────
1375
+ bold, dim, italic, underline, blink, blinkFast,
1376
+ inverse, hidden, strike, overline, framed,
1377
+ black, red, green, yellow, blue, magenta, cyan, white, gray,
1378
+ brightRed, brightGreen, brightYellow, brightBlue,
1379
+ brightMagenta, brightCyan, brightWhite,
1380
+ bgBlack, bgRed, bgGreen, bgYellow, bgBlue, bgMagenta,
1381
+ bgCyan, bgWhite, bgGray, bgBrightRed, bgBrightGreen,
1382
+ bgBrightYellow, bgBrightBlue, bgBrightMagenta,
1383
+ bgBrightCyan, bgBrightWhite,
1384
+ gradient,
1385
+
1386
+ // ── Terminal control ─────────────────────────────
1387
+ Cursor, Erase, Scroll, Screen, Mouse, Window,
1388
+ Device, Special,
1389
+
1390
+ // ── Graphics protocols ───────────────────────────
1391
+ Sixel, KittyGfx, kittyGfx, InlineImage,
1392
+
1393
+ // ── Utilities ────────────────────────────────────
1394
+ strip, visibleLength,
1395
+ detectColorSupport, hasColor,
1396
+ parse, decodeSGR,
1397
+ ANSI_RE,
1398
+
1399
+ // ── Chainable builder ────────────────────────────
1400
+ AnsiString,
1401
+ }
1402
+ };