@promptctl/rich-js 0.17.0 → 0.18.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 (206) hide show
  1. package/README.md +13 -26
  2. package/package.json +7 -3
  3. package/dist/core/box.d.ts +0 -144
  4. package/dist/core/box.js +0 -391
  5. package/dist/core/cells.d.ts +0 -148
  6. package/dist/core/cells.js +0 -266
  7. package/dist/core/color.d.ts +0 -250
  8. package/dist/core/color.js +0 -1029
  9. package/dist/core/console.d.ts +0 -156
  10. package/dist/core/console.js +0 -472
  11. package/dist/core/emoji.d.ts +0 -24
  12. package/dist/core/emoji.js +0 -391
  13. package/dist/core/export-html.d.ts +0 -24
  14. package/dist/core/export-html.js +0 -106
  15. package/dist/core/export-lines.d.ts +0 -121
  16. package/dist/core/export-lines.js +0 -141
  17. package/dist/core/highlighter.d.ts +0 -33
  18. package/dist/core/highlighter.js +0 -124
  19. package/dist/core/json.d.ts +0 -27
  20. package/dist/core/json.js +0 -53
  21. package/dist/core/markup.d.ts +0 -97
  22. package/dist/core/markup.js +0 -619
  23. package/dist/core/measure.d.ts +0 -27
  24. package/dist/core/measure.js +0 -61
  25. package/dist/core/oklch.d.ts +0 -161
  26. package/dist/core/oklch.js +0 -312
  27. package/dist/core/osc8.d.ts +0 -68
  28. package/dist/core/osc8.js +0 -90
  29. package/dist/core/pretty.d.ts +0 -141
  30. package/dist/core/pretty.js +0 -472
  31. package/dist/core/protocol.d.ts +0 -137
  32. package/dist/core/protocol.js +0 -101
  33. package/dist/core/render.d.ts +0 -84
  34. package/dist/core/render.js +0 -145
  35. package/dist/core/segment.d.ts +0 -142
  36. package/dist/core/segment.js +0 -433
  37. package/dist/core/spinnerData.d.ts +0 -10
  38. package/dist/core/spinnerData.js +0 -115
  39. package/dist/core/strip.d.ts +0 -145
  40. package/dist/core/strip.js +0 -308
  41. package/dist/core/style.d.ts +0 -144
  42. package/dist/core/style.js +0 -723
  43. package/dist/core/subscription.d.ts +0 -12
  44. package/dist/core/subscription.js +0 -12
  45. package/dist/core/text.d.ts +0 -255
  46. package/dist/core/text.js +0 -990
  47. package/dist/core/wrap.d.ts +0 -41
  48. package/dist/core/wrap.js +0 -127
  49. package/dist/host/host-stream.d.ts +0 -30
  50. package/dist/host/host-stream.js +0 -35
  51. package/dist/host/index.d.ts +0 -3
  52. package/dist/host/index.js +0 -2
  53. package/dist/host/terminal-host.d.ts +0 -143
  54. package/dist/host/terminal-host.js +0 -132
  55. package/dist/index.d.ts +0 -87
  56. package/dist/index.js +0 -104
  57. package/dist/node/prompt.d.ts +0 -21
  58. package/dist/node/prompt.js +0 -30
  59. package/dist/node/save.d.ts +0 -17
  60. package/dist/node/save.js +0 -21
  61. package/dist/node/terminal-host.d.ts +0 -84
  62. package/dist/node/terminal-host.js +0 -160
  63. package/dist/node/traceback.d.ts +0 -27
  64. package/dist/node/traceback.js +0 -112
  65. package/dist/renderables/align.d.ts +0 -16
  66. package/dist/renderables/align.js +0 -46
  67. package/dist/renderables/columns.d.ts +0 -61
  68. package/dist/renderables/columns.js +0 -168
  69. package/dist/renderables/constrain.d.ts +0 -15
  70. package/dist/renderables/constrain.js +0 -37
  71. package/dist/renderables/flexStrip.d.ts +0 -41
  72. package/dist/renderables/flexStrip.js +0 -200
  73. package/dist/renderables/group.d.ts +0 -11
  74. package/dist/renderables/group.js +0 -15
  75. package/dist/renderables/layout.d.ts +0 -92
  76. package/dist/renderables/layout.js +0 -315
  77. package/dist/renderables/live.d.ts +0 -47
  78. package/dist/renderables/live.js +0 -131
  79. package/dist/renderables/markdown.d.ts +0 -24
  80. package/dist/renderables/markdown.js +0 -182
  81. package/dist/renderables/padding.d.ts +0 -38
  82. package/dist/renderables/padding.js +0 -140
  83. package/dist/renderables/panel.d.ts +0 -116
  84. package/dist/renderables/panel.js +0 -322
  85. package/dist/renderables/progress.d.ts +0 -90
  86. package/dist/renderables/progress.js +0 -241
  87. package/dist/renderables/progressBar.d.ts +0 -31
  88. package/dist/renderables/progressBar.js +0 -52
  89. package/dist/renderables/prompt.d.ts +0 -49
  90. package/dist/renderables/prompt.js +0 -125
  91. package/dist/renderables/rule.d.ts +0 -24
  92. package/dist/renderables/rule.js +0 -90
  93. package/dist/renderables/spinner.d.ts +0 -29
  94. package/dist/renderables/spinner.js +0 -64
  95. package/dist/renderables/status.d.ts +0 -23
  96. package/dist/renderables/status.js +0 -60
  97. package/dist/renderables/syntax.d.ts +0 -35
  98. package/dist/renderables/syntax.js +0 -114
  99. package/dist/renderables/table.d.ts +0 -182
  100. package/dist/renderables/table.js +0 -697
  101. package/dist/renderables/traceback.d.ts +0 -31
  102. package/dist/renderables/traceback.js +0 -109
  103. package/dist/renderables/tree.d.ts +0 -54
  104. package/dist/renderables/tree.js +0 -159
  105. package/dist/template-bindings/color-funcs.d.ts +0 -87
  106. package/dist/template-bindings/color-funcs.js +0 -219
  107. package/dist/template-bindings/helpers.d.ts +0 -24
  108. package/dist/template-bindings/helpers.js +0 -48
  109. package/dist/template-bindings/index.d.ts +0 -107
  110. package/dist/template-bindings/index.js +0 -144
  111. package/dist/template-bindings/palette-funcs.d.ts +0 -94
  112. package/dist/template-bindings/palette-funcs.js +0 -151
  113. package/dist/template-bindings/style-funcs.d.ts +0 -28
  114. package/dist/template-bindings/style-funcs.js +0 -151
  115. package/dist/themes/buildPalette.d.ts +0 -36
  116. package/dist/themes/buildPalette.js +0 -56
  117. package/dist/themes/colorMath.d.ts +0 -82
  118. package/dist/themes/colorMath.js +0 -254
  119. package/dist/themes/colorRef.d.ts +0 -51
  120. package/dist/themes/colorRef.js +0 -96
  121. package/dist/themes/data/atom-one-dark.d.ts +0 -3
  122. package/dist/themes/data/atom-one-dark.js +0 -158
  123. package/dist/themes/data/atom-one-light.d.ts +0 -3
  124. package/dist/themes/data/atom-one-light.js +0 -158
  125. package/dist/themes/data/catppuccin-frappe.d.ts +0 -3
  126. package/dist/themes/data/catppuccin-frappe.js +0 -158
  127. package/dist/themes/data/catppuccin-latte.d.ts +0 -3
  128. package/dist/themes/data/catppuccin-latte.js +0 -158
  129. package/dist/themes/data/catppuccin-macchiato.d.ts +0 -3
  130. package/dist/themes/data/catppuccin-macchiato.js +0 -158
  131. package/dist/themes/data/catppuccin-mocha.d.ts +0 -3
  132. package/dist/themes/data/catppuccin-mocha.js +0 -158
  133. package/dist/themes/data/cyberpunk.d.ts +0 -17
  134. package/dist/themes/data/cyberpunk.js +0 -191
  135. package/dist/themes/data/default.d.ts +0 -3
  136. package/dist/themes/data/default.js +0 -158
  137. package/dist/themes/data/dracula.d.ts +0 -3
  138. package/dist/themes/data/dracula.js +0 -158
  139. package/dist/themes/data/flexoki.d.ts +0 -3
  140. package/dist/themes/data/flexoki.js +0 -158
  141. package/dist/themes/data/gruvbox.d.ts +0 -3
  142. package/dist/themes/data/gruvbox.js +0 -158
  143. package/dist/themes/data/index.d.ts +0 -35
  144. package/dist/themes/data/index.js +0 -64
  145. package/dist/themes/data/monokai.d.ts +0 -3
  146. package/dist/themes/data/monokai.js +0 -158
  147. package/dist/themes/data/nord.d.ts +0 -3
  148. package/dist/themes/data/nord.js +0 -158
  149. package/dist/themes/data/rose-pine-dawn.d.ts +0 -3
  150. package/dist/themes/data/rose-pine-dawn.js +0 -158
  151. package/dist/themes/data/rose-pine-moon.d.ts +0 -3
  152. package/dist/themes/data/rose-pine-moon.js +0 -158
  153. package/dist/themes/data/rose-pine.d.ts +0 -3
  154. package/dist/themes/data/rose-pine.js +0 -158
  155. package/dist/themes/data/solarized-dark.d.ts +0 -3
  156. package/dist/themes/data/solarized-dark.js +0 -158
  157. package/dist/themes/data/solarized-light.d.ts +0 -3
  158. package/dist/themes/data/solarized-light.js +0 -158
  159. package/dist/themes/data/svg-export.d.ts +0 -3
  160. package/dist/themes/data/svg-export.js +0 -158
  161. package/dist/themes/data/textual-ansi.d.ts +0 -3
  162. package/dist/themes/data/textual-ansi.js +0 -158
  163. package/dist/themes/data/textual-dark.d.ts +0 -3
  164. package/dist/themes/data/textual-dark.js +0 -158
  165. package/dist/themes/data/textual-light.d.ts +0 -3
  166. package/dist/themes/data/textual-light.js +0 -158
  167. package/dist/themes/data/tokyo-night.d.ts +0 -3
  168. package/dist/themes/data/tokyo-night.js +0 -158
  169. package/dist/themes/data/types.d.ts +0 -15
  170. package/dist/themes/data/types.js +0 -1
  171. package/dist/themes/palette.d.ts +0 -21
  172. package/dist/themes/palette.js +0 -28
  173. package/dist/themes/ramp.d.ts +0 -83
  174. package/dist/themes/ramp.js +0 -122
  175. package/dist/themes/registry.d.ts +0 -43
  176. package/dist/themes/registry.js +0 -82
  177. package/dist/themes/terminalThemes.d.ts +0 -54
  178. package/dist/themes/terminalThemes.js +0 -68
  179. package/dist/themes/transpose.d.ts +0 -87
  180. package/dist/themes/transpose.js +0 -138
  181. package/dist/widgets/button.d.ts +0 -49
  182. package/dist/widgets/button.js +0 -206
  183. package/dist/widgets/checkbox.d.ts +0 -41
  184. package/dist/widgets/checkbox.js +0 -155
  185. package/dist/widgets/dropdown.d.ts +0 -67
  186. package/dist/widgets/dropdown.js +0 -453
  187. package/dist/widgets/event-router.d.ts +0 -78
  188. package/dist/widgets/event-router.js +0 -622
  189. package/dist/widgets/focus-manager.d.ts +0 -26
  190. package/dist/widgets/focus-manager.js +0 -193
  191. package/dist/widgets/index.d.ts +0 -22
  192. package/dist/widgets/index.js +0 -15
  193. package/dist/widgets/screen.d.ts +0 -98
  194. package/dist/widgets/screen.js +0 -530
  195. package/dist/widgets/slider.d.ts +0 -57
  196. package/dist/widgets/slider.js +0 -270
  197. package/dist/widgets/static-item.d.ts +0 -40
  198. package/dist/widgets/static-item.js +0 -60
  199. package/dist/widgets/text-input.d.ts +0 -274
  200. package/dist/widgets/text-input.js +0 -1162
  201. package/dist/widgets/toggle.d.ts +0 -44
  202. package/dist/widgets/toggle.js +0 -179
  203. package/dist/widgets/types.d.ts +0 -108
  204. package/dist/widgets/types.js +0 -31
  205. package/dist/widgets/widget-base.d.ts +0 -42
  206. package/dist/widgets/widget-base.js +0 -173
@@ -1,1029 +0,0 @@
1
- /**
2
- * Terminal color representation, parsing, downgrading, and ANSI code generation.
3
- */
4
- // --- ColorRgba ---
5
- function hex2(byte) {
6
- return byte.toString(16).padStart(2, "0");
7
- }
8
- function assertChannel(name, v) {
9
- if (!Number.isInteger(v) || v < 0 || v > 255) {
10
- throw new RangeError(`ColorRgba.${name} must be an integer in [0, 255]; got ${v}`);
11
- }
12
- }
13
- /**
14
- * Immutable RGBA color value. Alpha defaults to 1 (fully opaque).
15
- *
16
- * [LAW:single-enforcer] The constructor is the sole validation site for
17
- * channel/alpha invariants. Float-arithmetic callers (HSL roundtrips, blends,
18
- * lerps) are responsible for `Math.round` + clamp before construction; the
19
- * constructor throws rather than silently masking out-of-range input.
20
- */
21
- export class ColorRgba {
22
- red;
23
- green;
24
- blue;
25
- alpha;
26
- constructor(red, green, blue, alpha = 1) {
27
- this.red = red;
28
- this.green = green;
29
- this.blue = blue;
30
- this.alpha = alpha;
31
- assertChannel("red", red);
32
- assertChannel("green", green);
33
- assertChannel("blue", blue);
34
- if (!Number.isFinite(alpha) || alpha < 0 || alpha > 1) {
35
- throw new RangeError(`ColorRgba.alpha must be a finite number in [0, 1]; got ${alpha}`);
36
- }
37
- }
38
- /** 6-char `#RRGGBB` when fully opaque, 8-char `#RRGGBBAA` otherwise. */
39
- get hex() {
40
- const rgb = "#" + hex2(this.red) + hex2(this.green) + hex2(this.blue);
41
- return this.alpha === 1 ? rgb : rgb + hex2(Math.round(this.alpha * 255));
42
- }
43
- /** `rgb(r,g,b)` when fully opaque, `rgba(r,g,b,a)` otherwise. */
44
- get rgb() {
45
- return this.alpha === 1
46
- ? `rgb(${this.red},${this.green},${this.blue})`
47
- : `rgba(${this.red},${this.green},${this.blue},${this.alpha})`;
48
- }
49
- /** [r/255, g/255, b/255, alpha] — alpha is already 0..1, no division. */
50
- get normalized() {
51
- return [this.red / 255, this.green / 255, this.blue / 255, this.alpha];
52
- }
53
- /**
54
- * Composite this color over an opaque background. Returns a fully opaque
55
- * ColorRgba (alpha=1). Per-channel linear interpolation by alpha.
56
- *
57
- * [LAW:dataflow-not-control-flow] alpha=1 short-circuits to `this`, so
58
- * callers can invoke this unconditionally; the data decides whether work
59
- * happens.
60
- */
61
- compositeOver(bg) {
62
- if (this.alpha === 1)
63
- return this;
64
- const t = this.alpha;
65
- return new ColorRgba(Math.round(bg.red + (this.red - bg.red) * t), Math.round(bg.green + (this.green - bg.green) * t), Math.round(bg.blue + (this.blue - bg.blue) * t), 1);
66
- }
67
- }
68
- /**
69
- * The surface a terminal draws a translucent colour over. A terminal cannot
70
- * know what lies under its cells, so the SGR writer (`Style.toSgrCodes`), the
71
- * strip's seam test and the contrast choosers (`themes/colorMath`) all
72
- * composite over this one colour. [LAW:one-source-of-truth] One constant, so
73
- * the colour text is chosen against is the colour the writer draws.
74
- */
75
- export const SURFACE_BLACK = new ColorRgba(0, 0, 0);
76
- /**
77
- * WCAG 2.x relative luminance (0..1) of an opaque color. The single
78
- * luminance function in the codebase — `contrastFor`, `contrastRatio`, and
79
- * any caller that needs to reason about readability all funnel through it.
80
- * [LAW:one-source-of-truth]
81
- */
82
- export function relativeLuminance(c) {
83
- const ch = (v) => {
84
- const x = v / 255;
85
- return x <= 0.03928 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
86
- };
87
- return 0.2126 * ch(c.red) + 0.7152 * ch(c.green) + 0.0722 * ch(c.blue);
88
- }
89
- /**
90
- * WCAG 2.x contrast ratio between two colors, in [1, 21]. Symmetric — the
91
- * order of arguments does not matter. 4.5 is the AA threshold for normal
92
- * text, 3.0 for large text.
93
- *
94
- * Assumes opaque inputs: alpha is ignored, since the displayed contrast of a
95
- * translucent color depends on what it composites over. For a translucent
96
- * foreground, flatten it first (or use `ensureContrast`, which does).
97
- */
98
- export function contrastRatio(a, b) {
99
- return luminanceRatio(relativeLuminance(a), relativeLuminance(b));
100
- }
101
- // [LAW:single-enforcer] The WCAG ratio over two relative luminances — the one
102
- // formula `contrastRatio` and `ColorTable.matchReadable` (which caches its
103
- // entries' luminances) both measure with.
104
- function luminanceRatio(la, lb) {
105
- return (Math.max(la, lb) + 0.05) / (Math.min(la, lb) + 0.05);
106
- }
107
- // --- ColorTable ---
108
- /**
109
- * An indexed palette: entry `i` of `colors` is terminal index `firstIndex + i`.
110
- * `firstIndex` lets a table hold only the part of a palette a downgrade may
111
- * choose (the 256-colour cube and grey ramp start at 16) while every index it
112
- * reports is the terminal's own.
113
- */
114
- // [LAW:single-enforcer] The one size policy for ColorTable's memos: a key is
115
- // derived from colours a long-running host computes without end (ramp stops,
116
- // mixes), so an unbounded map grows with every render. Clearing at the cap is
117
- // the policy `cellLen` already uses; a refill costs one table scan per key.
118
- const TABLE_CACHE_MAX = 4096;
119
- function remember(cache, key, index) {
120
- if (cache.size >= TABLE_CACHE_MAX)
121
- cache.clear();
122
- cache.set(key, index);
123
- return index;
124
- }
125
- // [LAW:one-source-of-truth] The one distance every table scan ranks by, so
126
- // `matchWhere`'s "nearest by the distance `match` uses" cannot drift.
127
- function rgbDistance(a, b) {
128
- const dr = a.red - b.red;
129
- const dg = a.green - b.green;
130
- const db = a.blue - b.blue;
131
- return dr * dr + dg * dg + db * db;
132
- }
133
- export class ColorTable {
134
- colors;
135
- firstIndex;
136
- matchCache = new Map();
137
- readableCache = new Map();
138
- constructor(colors, firstIndex = 0) {
139
- this.colors = colors;
140
- this.firstIndex = firstIndex;
141
- }
142
- get(index) {
143
- return this.colors[index - this.firstIndex];
144
- }
145
- luminanceCache;
146
- /** Each entry's relative luminance, computed once per table. */
147
- luminances() {
148
- this.luminanceCache ??= this.colors.map(relativeLuminance);
149
- return this.luminanceCache;
150
- }
151
- /** How many entries the table holds (terminal indices `firstIndex`…). */
152
- get size() {
153
- return this.colors.length;
154
- }
155
- /**
156
- * Finds the nearest table index to the given color (Euclidean RGB distance, cached).
157
- * Alpha is part of the cache key so two values that differ only in alpha
158
- * don't collide, but is not used in the distance metric.
159
- */
160
- match(value) {
161
- const key = `${value.red},${value.green},${value.blue},${value.alpha}`;
162
- const cached = this.matchCache.get(key);
163
- if (cached !== undefined)
164
- return cached;
165
- let bestIndex = 0;
166
- let bestDist = Infinity;
167
- for (let i = 0; i < this.colors.length; i++) {
168
- const c = this.colors[i];
169
- const dist = rgbDistance(c, value);
170
- if (dist < bestDist) {
171
- bestDist = dist;
172
- bestIndex = i;
173
- }
174
- }
175
- return remember(this.matchCache, key, this.firstIndex + bestIndex);
176
- }
177
- /**
178
- * The nearest entry to `value` (the distance `match` uses) among those that
179
- * clear `minRatio` against `on`; when none does, the entry with the most
180
- * contrast against `on`. Text downgraded on its own background: `match`
181
- * moves text and background independently, and two independent roundings
182
- * can meet in the middle, so a pair that read at 4.5:1 in truecolor can
183
- * draw at 2:1. [LAW:dataflow-not-control-flow] One scan scores every entry;
184
- * the ratio decides which one wins.
185
- */
186
- matchReadable(value, on, minRatio) {
187
- const key = `${value.red},${value.green},${value.blue}|${on.red},${on.green},${on.blue}|${minRatio}`;
188
- const cached = this.readableCache.get(key);
189
- if (cached !== undefined)
190
- return cached;
191
- const lOn = relativeLuminance(on);
192
- let best = 0;
193
- let bestPasses = false;
194
- let bestScore = -Infinity;
195
- for (let i = 0; i < this.colors.length; i++) {
196
- const c = this.colors[i];
197
- const lc = this.luminances()[i];
198
- const ratio = luminanceRatio(lc, lOn);
199
- const passes = ratio >= minRatio;
200
- // A passing entry scores by closeness; a failing one only by contrast,
201
- // and loses to every passing one.
202
- const score = passes ? -rgbDistance(c, value) : ratio;
203
- if ((passes && !bestPasses) ||
204
- (passes === bestPasses && score > bestScore)) {
205
- best = i;
206
- bestPasses = passes;
207
- bestScore = score;
208
- }
209
- }
210
- return remember(this.readableCache, key, this.firstIndex + best);
211
- }
212
- /**
213
- * The nearest entry to `value` (the distance `match` uses) among those
214
- * `accept` takes, given each entry's colour and terminal index; `undefined`
215
- * when it takes none. Entries are offered nearest-first (ties to the lower
216
- * index) and the first taken wins, so an expensive predicate runs only as
217
- * far out as the answer. Uncached: the predicate is the caller's, and a
218
- * closure has no key.
219
- */
220
- matchWhere(value, accept) {
221
- const dist = this.colors.map((c) => rgbDistance(c, value));
222
- const nearestFirst = [...dist.keys()].sort((a, b) => dist[a] - dist[b]);
223
- const found = nearestFirst.find((i) => accept(this.colors[i], this.firstIndex + i));
224
- return found === undefined ? undefined : this.firstIndex + found;
225
- }
226
- }
227
- // --- Enums ---
228
- export var ColorDepth;
229
- (function (ColorDepth) {
230
- ColorDepth[ColorDepth["DEFAULT"] = 0] = "DEFAULT";
231
- ColorDepth[ColorDepth["STANDARD"] = 1] = "STANDARD";
232
- ColorDepth[ColorDepth["EIGHT_BIT"] = 2] = "EIGHT_BIT";
233
- ColorDepth[ColorDepth["TRUECOLOR"] = 3] = "TRUECOLOR";
234
- ColorDepth[ColorDepth["WINDOWS"] = 4] = "WINDOWS";
235
- })(ColorDepth || (ColorDepth = {}));
236
- // [LAW:one-source-of-truth] One table covers every recognized string form
237
- // that resolves to a ColorDepth: user-facing CLI/config specs, FORCE_COLOR
238
- // values (the chalk/supports-color convention), TERM_PROGRAM identifiers,
239
- // and exact TERM names whose color capability is known. Keys are disjoint
240
- // across these sources, so one table is honest. `null` means "no color".
241
- // "auto" is intentionally absent — it routes to env detection.
242
- const STRING_TO_DEPTH = {
243
- // CLI/config specs
244
- truecolor: ColorDepth.TRUECOLOR,
245
- "256": ColorDepth.EIGHT_BIT,
246
- ansi: ColorDepth.STANDARD,
247
- none: null,
248
- // FORCE_COLOR values
249
- "0": null,
250
- false: null,
251
- "1": ColorDepth.STANDARD,
252
- true: ColorDepth.STANDARD,
253
- "2": ColorDepth.EIGHT_BIT,
254
- "3": ColorDepth.TRUECOLOR,
255
- // TERM_PROGRAM identifiers
256
- "iTerm.app": ColorDepth.TRUECOLOR,
257
- Apple_Terminal: ColorDepth.EIGHT_BIT,
258
- vscode: ColorDepth.TRUECOLOR,
259
- Tabby: ColorDepth.TRUECOLOR,
260
- // Known truecolor TERM names
261
- "xterm-kitty": ColorDepth.TRUECOLOR,
262
- "xterm-ghostty": ColorDepth.TRUECOLOR,
263
- wezterm: ColorDepth.TRUECOLOR,
264
- alacritty: ColorDepth.TRUECOLOR,
265
- foot: ColorDepth.TRUECOLOR,
266
- contour: ColorDepth.TRUECOLOR,
267
- };
268
- /**
269
- * Detect the terminal's color capability from env + TTY state.
270
- *
271
- * Probes (in priority order): NO_COLOR (per https://no-color.org —
272
- * any non-empty value disables color), FORCE_COLOR (numeric/boolean override),
273
- * TTY presence, TERM=dumb/unknown, COLORTERM, known terminal/TERM_PROGRAM
274
- * names, and TERM regex patterns. Returns `null` for "no color".
275
- *
276
- * [LAW:dataflow-not-control-flow] Same probes run every call; variability is
277
- * in the env values, not in which checks execute.
278
- */
279
- export function detectColorSystem(options = {}) {
280
- // NO_COLOR and FORCE_COLOR are preferences about colour, not facts about the
281
- // terminal, so they sit outside the probe. NO_COLOR (any non-empty value)
282
- // beats FORCE_COLOR; FORCE_COLOR beats TTY/TERM detection.
283
- const noColor = envOf(options)["NO_COLOR"];
284
- if (noColor !== undefined && noColor !== "")
285
- return null;
286
- const forced = forcedColorSystem(envOf(options));
287
- return forced !== undefined ? forced : terminalColorSystem(options);
288
- }
289
- // FORCE_COLOR's depth: `undefined` when unset, `null` for its off values.
290
- function forcedColorSystem(env) {
291
- const force = env["FORCE_COLOR"];
292
- if (force === undefined || force === "")
293
- return undefined;
294
- const mapped = STRING_TO_DEPTH[force];
295
- return mapped !== undefined ? mapped : ColorDepth.STANDARD;
296
- }
297
- function envOf(options) {
298
- return options.env ?? (typeof process !== "undefined" ? process.env : {});
299
- }
300
- // What the destination can draw, preferences aside: TTY presence,
301
- // TERM=dumb/unknown, COLORTERM, known terminal names, TERM patterns. `null`
302
- // here means the destination takes no escapes at all.
303
- function terminalColorSystem(options) {
304
- const env = envOf(options);
305
- const isTTY = options.isTTY ??
306
- (typeof process !== "undefined" ? (process.stdout?.isTTY ?? false) : false);
307
- if (!isTTY)
308
- return null;
309
- const term = env["TERM"] ?? "";
310
- if (term === "dumb" || term === "unknown")
311
- return null;
312
- const colorterm = env["COLORTERM"];
313
- if (colorterm === "truecolor" || colorterm === "24bit") {
314
- return ColorDepth.TRUECOLOR;
315
- }
316
- const termDepth = STRING_TO_DEPTH[term];
317
- if (termDepth !== undefined)
318
- return termDepth;
319
- const termProgram = env["TERM_PROGRAM"];
320
- if (termProgram !== undefined) {
321
- const mapped = STRING_TO_DEPTH[termProgram];
322
- if (mapped !== undefined)
323
- return mapped;
324
- }
325
- if (/-256(color)?$/i.test(term))
326
- return ColorDepth.EIGHT_BIT;
327
- if (/-truecolor$/i.test(term))
328
- return ColorDepth.TRUECOLOR;
329
- if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(term)) {
330
- return ColorDepth.STANDARD;
331
- }
332
- if (colorterm !== undefined && colorterm !== "")
333
- return ColorDepth.STANDARD;
334
- // Default: a terminal exists (isTTY=true) but we couldn't classify it.
335
- // Assume safe baseline rather than disabling color.
336
- return ColorDepth.STANDARD;
337
- }
338
- /**
339
- * Resolve a colour spec into a `Destination`.
340
- *
341
- * [LAW:single-enforcer] The one place a spec becomes both facts. A hyperlink is
342
- * not a colour: an explicit depth — `"none"` and `null` included — states a
343
- * colour choice and keeps links, and under `"auto"` links follow what the
344
- * terminal can take (no TTY, TERM=dumb: none) while NO_COLOR and FORCE_COLOR=0,
345
- * colour preferences, leave them alone. A FORCE_COLOR that forces colour on
346
- * declares the destination takes escapes, so it keeps links on a pipe too.
347
- */
348
- export function resolveDestination(spec, options) {
349
- if (spec !== "auto") {
350
- return {
351
- colorSystem: typeof spec === "string" ? resolveColorSystem(spec) : spec,
352
- hyperlinks: true,
353
- };
354
- }
355
- return {
356
- colorSystem: detectColorSystem(options),
357
- hyperlinks: (forcedColorSystem(envOf(options ?? {})) ?? null) !== null ||
358
- terminalColorSystem(options ?? {}) !== null,
359
- };
360
- }
361
- /**
362
- * Resolve a string spec into a `ColorDepth` (or `null` for no color).
363
- *
364
- * `"auto"` triggers env-based detection; all other recognized specs are
365
- * direct table lookups against `STRING_TO_DEPTH`. Throws on unknown specs
366
- * — silent fallback would mask user typos.
367
- *
368
- * [LAW:single-enforcer] All string→ColorDepth resolution flows through here.
369
- */
370
- export function resolveColorSystem(spec, options) {
371
- if (spec === "auto")
372
- return detectColorSystem(options);
373
- if (Object.hasOwn(STRING_TO_DEPTH, spec))
374
- return STRING_TO_DEPTH[spec];
375
- throw new ColorParseError(`Unknown color depth spec: ${JSON.stringify(spec)} (expected "auto", "truecolor", "256", "ansi", or "none")`);
376
- }
377
- // --- ColorSpec ---
378
- export class ColorParseError extends Error {
379
- constructor(message) {
380
- super(message);
381
- this.name = "ColorParseError";
382
- }
383
- }
384
- // [LAW:one-source-of-truth] Parse cache is the single source for parsed ColorSpec instances
385
- const parseCache = new Map();
386
- export class ColorSpec {
387
- name;
388
- type;
389
- number;
390
- value;
391
- downgradeCache = new Map();
392
- constructor(name, type, number, value) {
393
- this.name = name;
394
- this.type = type;
395
- this.number = number;
396
- this.value = value;
397
- }
398
- get isDefault() {
399
- return this.type === ColorDepth.DEFAULT;
400
- }
401
- /**
402
- * The colour every terminal draws this spec as, where that is fixed — before
403
- * any alpha is flattened, so a translucent value is drawn composited over
404
- * its ground (`flattenAlpha`) and should be measured that way: a
405
- * truecolor value, or a 256-colour cube or grey-ramp entry (xterm fixes
406
- * indices 16–255, and `fromAnsi` types only those as EIGHT_BIT). ANSI 0–15
407
- * and the default colour are the terminal theme's own, so they have none.
408
- */
409
- get fixedValue() {
410
- switch (this.type) {
411
- case ColorDepth.TRUECOLOR:
412
- return this.value;
413
- case ColorDepth.EIGHT_BIT:
414
- // The constructor admits an EIGHT_BIT spec at 0–15; those are the
415
- // theme's own slots whatever depth names them.
416
- return this.number < 16 ? undefined : EIGHT_BIT_TABLE.get(this.number);
417
- case ColorDepth.DEFAULT:
418
- case ColorDepth.STANDARD:
419
- case ColorDepth.WINDOWS:
420
- return undefined;
421
- }
422
- }
423
- get isSystemDefined() {
424
- return (this.type === ColorDepth.STANDARD || this.type === ColorDepth.WINDOWS);
425
- }
426
- /**
427
- * Generates SGR parameter strings for this color.
428
- */
429
- getAnsiCodes(foreground = true) {
430
- switch (this.type) {
431
- case ColorDepth.DEFAULT:
432
- return [foreground ? "39" : "49"];
433
- case ColorDepth.STANDARD: {
434
- const n = this.number;
435
- if (foreground) {
436
- return n < 8 ? [`${30 + n}`] : [`${90 + n - 8}`];
437
- }
438
- return n < 8 ? [`${40 + n}`] : [`${100 + n - 8}`];
439
- }
440
- case ColorDepth.EIGHT_BIT:
441
- return [foreground ? "38" : "48", "5", `${this.number}`];
442
- case ColorDepth.TRUECOLOR: {
443
- const t = this.value;
444
- return [
445
- foreground ? "38" : "48",
446
- "2",
447
- `${t.red}`,
448
- `${t.green}`,
449
- `${t.blue}`,
450
- ];
451
- }
452
- case ColorDepth.WINDOWS: {
453
- const n = this.number;
454
- if (foreground) {
455
- return n < 8 ? [`${30 + n}`] : [`${90 + n - 8}`];
456
- }
457
- return n < 8 ? [`${40 + n}`] : [`${100 + n - 8}`];
458
- }
459
- }
460
- }
461
- /**
462
- * Composite this color's alpha (if any) against an opaque background,
463
- * returning a fully-opaque ColorSpec. Non-truecolor specs (palette
464
- * indices, default) have no alpha and pass through unchanged.
465
- *
466
- * [LAW:single-enforcer] Sole alpha-flattening site for the render
467
- * pipeline. Run *before* downgrade — otherwise palette matching on the
468
- * still-translucent RGB silently drops alpha (the "flatten then lose
469
- * alpha" path the unification ticket forbids).
470
- *
471
- * [LAW:dataflow-not-control-flow] `ColorRgba.compositeOver` is a no-op
472
- * when alpha=1, so callers invoke this unconditionally; the data
473
- * (alpha value) decides whether work happens.
474
- */
475
- flattenAlpha(bg) {
476
- if (this.type !== ColorDepth.TRUECOLOR || !this.value)
477
- return this;
478
- const flat = this.value.compositeOver(bg);
479
- return flat === this.value ? this : ColorSpec.fromRgba(flat);
480
- }
481
- /**
482
- * Downgrade to a lower-fidelity color depth. Cached.
483
- */
484
- downgrade(targetSystem) {
485
- if (this.type === ColorDepth.DEFAULT)
486
- return this;
487
- if (this.type <= targetSystem)
488
- return this;
489
- const cached = this.downgradeCache.get(targetSystem);
490
- if (cached)
491
- return cached;
492
- const result = this.performDowngrade(targetSystem);
493
- this.downgradeCache.set(targetSystem, result);
494
- return result;
495
- }
496
- /**
497
- * Resolves to an actual RGB(A) value for any color type.
498
- */
499
- getTruecolor(theme, foreground = true) {
500
- switch (this.type) {
501
- case ColorDepth.TRUECOLOR:
502
- return this.value;
503
- case ColorDepth.EIGHT_BIT:
504
- return EIGHT_BIT_TABLE.get(this.number);
505
- case ColorDepth.STANDARD: {
506
- const t = theme ?? INTERNAL_DEFAULT_THEME;
507
- return t.ansiColors.get(this.number);
508
- }
509
- case ColorDepth.DEFAULT: {
510
- const t = theme ?? INTERNAL_DEFAULT_THEME;
511
- return foreground ? t.foregroundColor : t.backgroundColor;
512
- }
513
- case ColorDepth.WINDOWS: {
514
- const t = theme ?? INTERNAL_DEFAULT_THEME;
515
- return t.ansiColors.get(this.number);
516
- }
517
- }
518
- }
519
- // --- Static factories ---
520
- static default() {
521
- return new ColorSpec("default", ColorDepth.DEFAULT);
522
- }
523
- static fromAnsi(n) {
524
- const type = n < 16 ? ColorDepth.STANDARD : ColorDepth.EIGHT_BIT;
525
- return new ColorSpec(`color(${n})`, type, n);
526
- }
527
- static fromRgba(value) {
528
- return new ColorSpec(value.hex, ColorDepth.TRUECOLOR, undefined, value);
529
- }
530
- static fromRgb(r, g, b) {
531
- return ColorSpec.fromRgba(new ColorRgba(r, g, b));
532
- }
533
- /**
534
- * Parse a color string. Cached — identical strings return the same instance.
535
- */
536
- static parse(colorString) {
537
- const key = colorString.toLowerCase().trim();
538
- const cached = parseCache.get(key);
539
- if (cached)
540
- return cached;
541
- const result = parseSingle(key);
542
- parseCache.set(key, result);
543
- return result;
544
- }
545
- // --- private ---
546
- performDowngrade(targetSystem) {
547
- // Get the true RGB of this color
548
- const triplet = this.getTruecolor();
549
- switch (targetSystem) {
550
- case ColorDepth.EIGHT_BIT: {
551
- const index = EIGHT_BIT_DOWNGRADE_TABLE.match(triplet);
552
- return ColorSpec.fromAnsi(index);
553
- }
554
- case ColorDepth.STANDARD: {
555
- const index = STANDARD_TABLE.match(triplet);
556
- return new ColorSpec(`color(${index})`, ColorDepth.STANDARD, index);
557
- }
558
- // WINDOWS is a detection result (max enum value), not a downgrade target.
559
- // The `this.type <= targetSystem` guard in downgrade() always short-circuits
560
- // before reaching this method with WINDOWS, so this case is unreachable.
561
- case ColorDepth.WINDOWS:
562
- case ColorDepth.TRUECOLOR:
563
- return this;
564
- case ColorDepth.DEFAULT:
565
- return ColorSpec.default();
566
- }
567
- }
568
- }
569
- // --- Parsing internals ---
570
- const HEX_RE = /^#([0-9a-f]{6})$/;
571
- const HEX_RGBA_RE = /^#([0-9a-f]{8})$/;
572
- const RGB_RE = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/;
573
- const COLOR_NUMBER_RE = /^color\((\d{1,3})\)$/;
574
- function parseSingle(key) {
575
- if (key === "default" || key === "") {
576
- return ColorSpec.default();
577
- }
578
- // Named color
579
- const namedIndex = ANSI_COLOR_NAMES[key];
580
- if (namedIndex !== undefined) {
581
- const type = namedIndex < 16 ? ColorDepth.STANDARD : ColorDepth.EIGHT_BIT;
582
- return new ColorSpec(key, type, namedIndex);
583
- }
584
- // Hex (8-char with alpha takes precedence over 6-char to avoid the 6-char
585
- // regex matching a prefix of an 8-char string).
586
- const hexRgbaMatch = HEX_RGBA_RE.exec(key);
587
- if (hexRgbaMatch) {
588
- return new ColorSpec(key, ColorDepth.TRUECOLOR, undefined, parseRgbaHex(hexRgbaMatch[1]));
589
- }
590
- const hexMatch = HEX_RE.exec(key);
591
- if (hexMatch) {
592
- return new ColorSpec(key, ColorDepth.TRUECOLOR, undefined, parseRgbHex(hexMatch[1]));
593
- }
594
- // rgb()
595
- const rgbMatch = RGB_RE.exec(key);
596
- if (rgbMatch) {
597
- const r = parseInt(rgbMatch[1], 10);
598
- const g = parseInt(rgbMatch[2], 10);
599
- const b = parseInt(rgbMatch[3], 10);
600
- return new ColorSpec(key, ColorDepth.TRUECOLOR, undefined, new ColorRgba(r, g, b));
601
- }
602
- // color(N)
603
- const numMatch = COLOR_NUMBER_RE.exec(key);
604
- if (numMatch) {
605
- const n = parseInt(numMatch[1], 10);
606
- if (n > 255) {
607
- throw new ColorParseError(`ColorSpec number ${n} is out of range (0-255)`);
608
- }
609
- const type = n < 16 ? ColorDepth.STANDARD : ColorDepth.EIGHT_BIT;
610
- return new ColorSpec(key, type, n);
611
- }
612
- throw new ColorParseError(`Failed to parse color: "${key}"`);
613
- }
614
- // --- Utility functions ---
615
- export function parseRgbHex(hex) {
616
- const r = parseInt(hex.slice(0, 2), 16);
617
- const g = parseInt(hex.slice(2, 4), 16);
618
- const b = parseInt(hex.slice(4, 6), 16);
619
- return new ColorRgba(r, g, b);
620
- }
621
- export function parseRgbaHex(hex) {
622
- const r = parseInt(hex.slice(0, 2), 16);
623
- const g = parseInt(hex.slice(2, 4), 16);
624
- const b = parseInt(hex.slice(4, 6), 16);
625
- const a = parseInt(hex.slice(6, 8), 16) / 255;
626
- return new ColorRgba(r, g, b, a);
627
- }
628
- export function blendRgb(color1, color2, crossFade = 0.5) {
629
- return new ColorRgba(Math.round(color1.red + (color2.red - color1.red) * crossFade), Math.round(color1.green + (color2.green - color1.green) * crossFade), Math.round(color1.blue + (color2.blue - color1.blue) * crossFade), color1.alpha + (color2.alpha - color1.alpha) * crossFade);
630
- }
631
- // --- TerminalTheme ---
632
- /**
633
- * A terminal theme — surface/foreground baseline, the ANSI 16/256 LUT, and a
634
- * semantic palette.
635
- *
636
- * **`ansiColors` is the canonical ANSI table, not a per-theme override.** All
637
- * preset themes in this codebase use `STANDARD_TABLE` for `ansiColors`. Theme
638
- * identity lives entirely in `palette` (primary, accent, text-*, surface, ...);
639
- * `ColorSpec.parse("red")` is intentionally consistent across themes — same
640
- * design as Textual itself, which models theming at the truecolor/semantic
641
- * layer rather than overloading the ANSI 16. Custom callers building bespoke
642
- * themes that *do* want to retint ANSI 16 are free to pass their own
643
- * `ColorTable`; that path is supported but not how the built-in presets work.
644
- */
645
- export class TerminalTheme {
646
- backgroundColor;
647
- foregroundColor;
648
- ansiColors;
649
- palette;
650
- constructor(backgroundColor, foregroundColor, ansiColors, palette) {
651
- this.backgroundColor = backgroundColor;
652
- this.foregroundColor = foregroundColor;
653
- this.ansiColors = ansiColors;
654
- this.palette = palette;
655
- }
656
- }
657
- // --- ColorTable data ---
658
- function buildStandard16() {
659
- return [
660
- new ColorRgba(0, 0, 0), // 0 black
661
- new ColorRgba(128, 0, 0), // 1 red
662
- new ColorRgba(0, 128, 0), // 2 green
663
- new ColorRgba(128, 128, 0), // 3 yellow
664
- new ColorRgba(0, 0, 128), // 4 blue
665
- new ColorRgba(128, 0, 128), // 5 magenta
666
- new ColorRgba(0, 128, 128), // 6 cyan
667
- new ColorRgba(192, 192, 192), // 7 white
668
- new ColorRgba(128, 128, 128), // 8 bright_black
669
- new ColorRgba(255, 0, 0), // 9 bright_red
670
- new ColorRgba(0, 255, 0), // 10 bright_green
671
- new ColorRgba(255, 255, 0), // 11 bright_yellow
672
- new ColorRgba(0, 0, 255), // 12 bright_blue
673
- new ColorRgba(255, 0, 255), // 13 bright_magenta
674
- new ColorRgba(0, 255, 255), // 14 bright_cyan
675
- new ColorRgba(255, 255, 255), // 15 bright_white
676
- ];
677
- }
678
- function build256Table() {
679
- const colors = buildStandard16();
680
- // 6x6x6 color cube (indices 16-231)
681
- const levels = [0, 95, 135, 175, 215, 255];
682
- for (let r = 0; r < 6; r++) {
683
- for (let g = 0; g < 6; g++) {
684
- for (let b = 0; b < 6; b++) {
685
- colors.push(new ColorRgba(levels[r], levels[g], levels[b]));
686
- }
687
- }
688
- }
689
- // Grayscale ramp (indices 232-255)
690
- for (let i = 0; i < 24; i++) {
691
- const grey = 8 + 10 * i;
692
- colors.push(new ColorRgba(grey, grey, grey));
693
- }
694
- return colors;
695
- }
696
- function buildWindowsTable() {
697
- return [
698
- new ColorRgba(0, 0, 0), // 0
699
- new ColorRgba(0, 0, 128), // 1
700
- new ColorRgba(0, 128, 0), // 2
701
- new ColorRgba(0, 128, 128), // 3
702
- new ColorRgba(128, 0, 0), // 4
703
- new ColorRgba(128, 0, 128), // 5
704
- new ColorRgba(128, 128, 0), // 6
705
- new ColorRgba(192, 192, 192), // 7
706
- new ColorRgba(128, 128, 128), // 8
707
- new ColorRgba(0, 0, 255), // 9
708
- new ColorRgba(0, 255, 0), // 10
709
- new ColorRgba(0, 255, 255), // 11
710
- new ColorRgba(255, 0, 0), // 12
711
- new ColorRgba(255, 0, 255), // 13
712
- new ColorRgba(255, 255, 0), // 14
713
- new ColorRgba(255, 255, 255), // 15
714
- ];
715
- }
716
- export const STANDARD_TABLE = new ColorTable(buildStandard16());
717
- export const EIGHT_BIT_TABLE = new ColorTable(build256Table());
718
- /**
719
- * What a downgrade to 256 colours may choose: the cube and the grey ramp,
720
- * indices 16–255. Indices 0–15 are the terminal's own ANSI colours, which
721
- * every theme redefines, so their RGB is unknown and a match against them is
722
- * a guess; Python Rich never picks them either.
723
- */
724
- export const EIGHT_BIT_DOWNGRADE_TABLE = new ColorTable(build256Table().slice(16), 16);
725
- export const WINDOWS_TABLE = new ColorTable(buildWindowsTable());
726
- // --- Internal fallback theme ---
727
- //
728
- // [LAW:one-way-deps] Preset themes (DEFAULT_TERMINAL_THEME, MONOKAI, NORD, ...)
729
- // live in `src/themes/terminalThemes.ts` because they need `buildPalette` from
730
- // `themes/`. Keeping them out of `core/color.ts` makes the dependency strictly
731
- // `themes/* -> core/color`, with no runtime back-edge.
732
- //
733
- // `getTruecolor()` retains a fallback for callers that omit `theme`. The
734
- // fallback uses STANDARD_TABLE + black/white + an empty Palette — sufficient
735
- // for STANDARD/DEFAULT/WINDOWS lookups, which never read `palette`.
736
- //
737
- // Runtime-importing `Palette` from `themes/palette.ts` is safe: that module
738
- // only `import type`s from `core/color.ts`, so there is no runtime cycle.
739
- import { Palette } from "../themes/palette.js";
740
- const INTERNAL_DEFAULT_THEME = new TerminalTheme(new ColorRgba(0, 0, 0), new ColorRgba(255, 255, 255), STANDARD_TABLE, new Palette("default", true, new Map()));
741
- // --- ANSI ColorSpec Names ---
742
- // [LAW:one-source-of-truth] Single canonical mapping from name → palette index
743
- /**
744
- * The table with every `greyNN` name repeated under the `grayNN` spelling.
745
- *
746
- * Rich accepts both spellings and the xterm palette only defines one, so the
747
- * aliases are part of what this table *is* rather than a patch applied to it.
748
- *
749
- * [LAW:no-ambient-temporal-coupling] Which is why they arrive as an initializer
750
- * and not as the loop that used to mutate the finished map: that loop made "has
751
- * the aliases yet" a fact about module evaluation order, so the table had two
752
- * shapes and nothing in its type said which one you were holding. It also made
753
- * this module do work at import time, which is the claim `package.json`'s
754
- * `sideEffects: false` makes on its behalf — see
755
- * `test/seam/import-time-effects.ts`.
756
- */
757
- function withGrayAliases(names) {
758
- const aliases = Object.entries(names)
759
- .filter(([name]) => name.includes("grey"))
760
- .map(([name, index]) => [name.replace("grey", "gray"), index]);
761
- return { ...names, ...Object.fromEntries(aliases) };
762
- }
763
- export const ANSI_COLOR_NAMES = withGrayAliases({
764
- // Standard 16
765
- black: 0,
766
- red: 1,
767
- green: 2,
768
- yellow: 3,
769
- blue: 4,
770
- magenta: 5,
771
- cyan: 6,
772
- white: 7,
773
- bright_black: 8,
774
- bright_red: 9,
775
- bright_green: 10,
776
- bright_yellow: 11,
777
- bright_blue: 12,
778
- bright_magenta: 13,
779
- bright_cyan: 14,
780
- bright_white: 15,
781
- // 6x6x6 color cube (16-231)
782
- grey0: 16,
783
- navy_blue: 17,
784
- dark_blue: 18,
785
- blue3: 19,
786
- blue2: 20,
787
- blue1: 21,
788
- dark_green: 22,
789
- deep_sky_blue4: 23,
790
- deep_sky_blue5: 24,
791
- deep_sky_blue6: 25,
792
- dodger_blue3: 26,
793
- dodger_blue2: 27,
794
- green4: 28,
795
- spring_green4: 29,
796
- turquoise4: 30,
797
- deep_sky_blue3: 31,
798
- deep_sky_blue7: 32,
799
- dodger_blue1: 33,
800
- green3: 34,
801
- spring_green3: 35,
802
- dark_cyan: 36,
803
- light_sea_green: 37,
804
- deep_sky_blue2: 38,
805
- deep_sky_blue1: 39,
806
- green5: 40,
807
- spring_green5: 41,
808
- spring_green2: 42,
809
- cyan3: 43,
810
- dark_turquoise: 44,
811
- turquoise2: 45,
812
- green1: 46,
813
- spring_green6: 47,
814
- spring_green1: 48,
815
- medium_spring_green: 49,
816
- cyan2: 50,
817
- cyan1: 51,
818
- dark_red: 52,
819
- deep_pink4: 53,
820
- purple4: 54,
821
- purple5: 55,
822
- purple3: 56,
823
- blue_violet: 57,
824
- orange4: 58,
825
- grey37: 59,
826
- medium_purple4: 60,
827
- slate_blue3: 61,
828
- slate_blue4: 62,
829
- royal_blue1: 63,
830
- chartreuse4: 64,
831
- dark_sea_green4: 65,
832
- pale_turquoise4: 66,
833
- steel_blue: 67,
834
- steel_blue3: 68,
835
- cornflower_blue: 69,
836
- chartreuse3: 70,
837
- dark_sea_green5: 71,
838
- cadet_blue: 72,
839
- cadet_blue2: 73,
840
- sky_blue3: 74,
841
- steel_blue1: 75,
842
- chartreuse5: 76,
843
- pale_green3: 77,
844
- sea_green3: 78,
845
- aquamarine3: 79,
846
- medium_turquoise: 80,
847
- steel_blue2: 81,
848
- chartreuse2: 82,
849
- sea_green2: 83,
850
- sea_green1: 84,
851
- sea_green4: 85,
852
- aquamarine1: 86,
853
- dark_slate_gray2: 87,
854
- dark_red2: 88,
855
- deep_pink5: 89,
856
- dark_magenta: 90,
857
- dark_magenta2: 91,
858
- dark_violet: 92,
859
- purple2: 93,
860
- orange5: 94,
861
- light_pink4: 95,
862
- plum4: 96,
863
- medium_purple3: 97,
864
- medium_purple5: 98,
865
- slate_blue1: 99,
866
- yellow4: 100,
867
- wheat4: 101,
868
- grey53: 102,
869
- light_slate_grey: 103,
870
- medium_purple: 104,
871
- light_slate_blue: 105,
872
- yellow5: 106,
873
- dark_olive_green3: 107,
874
- dark_sea_green: 108,
875
- light_sky_blue3: 109,
876
- light_sky_blue4: 110,
877
- sky_blue2: 111,
878
- chartreuse6: 112,
879
- dark_olive_green4: 113,
880
- pale_green4: 114,
881
- dark_sea_green3: 115,
882
- dark_slate_gray3: 116,
883
- sky_blue1: 117,
884
- chartreuse1: 118,
885
- light_green: 119,
886
- light_green2: 120,
887
- pale_green1: 121,
888
- aquamarine2: 122,
889
- dark_slate_gray1: 123,
890
- red3: 124,
891
- deep_pink6: 125,
892
- medium_violet_red: 126,
893
- magenta3: 127,
894
- dark_violet2: 128,
895
- purple: 129,
896
- dark_orange3: 130,
897
- indian_red: 131,
898
- hot_pink3: 132,
899
- medium_orchid3: 133,
900
- medium_orchid: 134,
901
- medium_purple2: 135,
902
- dark_goldenrod: 136,
903
- light_salmon3: 137,
904
- rosy_brown: 138,
905
- grey63: 139,
906
- medium_purple6: 140,
907
- medium_purple1: 141,
908
- gold3: 142,
909
- dark_khaki: 143,
910
- navajo_white3: 144,
911
- grey69: 145,
912
- light_steel_blue3: 146,
913
- light_steel_blue: 147,
914
- yellow3: 148,
915
- dark_olive_green5: 149,
916
- dark_sea_green6: 150,
917
- dark_sea_green2: 151,
918
- light_cyan3: 152,
919
- light_sky_blue1: 153,
920
- green_yellow: 154,
921
- dark_olive_green2: 155,
922
- pale_green2: 156,
923
- dark_sea_green7: 157,
924
- dark_sea_green1: 158,
925
- pale_turquoise1: 159,
926
- red4: 160,
927
- deep_pink3: 161,
928
- deep_pink8: 162,
929
- magenta4: 163,
930
- magenta5: 164,
931
- magenta2: 165,
932
- dark_orange4: 166,
933
- indian_red2: 167,
934
- hot_pink4: 168,
935
- hot_pink2: 169,
936
- orchid: 170,
937
- medium_orchid1: 171,
938
- orange3: 172,
939
- light_salmon4: 173,
940
- light_pink3: 174,
941
- pink3: 175,
942
- plum3: 176,
943
- violet: 177,
944
- gold4: 178,
945
- light_goldenrod3: 179,
946
- tan: 180,
947
- misty_rose3: 181,
948
- thistle3: 182,
949
- plum2: 183,
950
- yellow6: 184,
951
- khaki3: 185,
952
- light_goldenrod2: 186,
953
- light_yellow3: 187,
954
- grey84: 188,
955
- light_steel_blue1: 189,
956
- yellow2: 190,
957
- dark_olive_green1: 191,
958
- dark_olive_green6: 192,
959
- dark_sea_green8: 193,
960
- honeydew2: 194,
961
- light_cyan1: 195,
962
- red1: 196,
963
- deep_pink2: 197,
964
- deep_pink1: 198,
965
- deep_pink9: 199,
966
- magenta6: 200,
967
- magenta1: 201,
968
- orange_red1: 202,
969
- indian_red1: 203,
970
- indian_red3: 204,
971
- hot_pink5: 205,
972
- hot_pink: 206,
973
- medium_orchid2: 207,
974
- dark_orange: 208,
975
- salmon1: 209,
976
- light_coral: 210,
977
- pale_violet_red1: 211,
978
- orchid2: 212,
979
- orchid1: 213,
980
- orange1: 214,
981
- sandy_brown: 215,
982
- light_salmon1: 216,
983
- light_pink1: 217,
984
- pink1: 218,
985
- plum1: 219,
986
- gold1: 220,
987
- light_goldenrod4: 221,
988
- light_goldenrod5: 222,
989
- navajo_white1: 223,
990
- misty_rose1: 224,
991
- thistle1: 225,
992
- yellow1: 226,
993
- light_goldenrod1: 227,
994
- khaki1: 228,
995
- wheat1: 229,
996
- cornsilk1: 230,
997
- grey100: 231,
998
- // Grayscale ramp (232-255)
999
- grey3: 232,
1000
- grey7: 233,
1001
- grey11: 234,
1002
- grey15: 235,
1003
- grey19: 236,
1004
- grey23: 237,
1005
- grey27: 238,
1006
- grey30: 239,
1007
- grey35: 240,
1008
- grey39: 241,
1009
- grey42: 242,
1010
- grey46: 243,
1011
- grey50: 244,
1012
- grey54: 245,
1013
- grey58: 246,
1014
- grey62: 247,
1015
- grey66: 248,
1016
- grey70: 249,
1017
- grey74: 250,
1018
- grey78: 251,
1019
- grey82: 252,
1020
- grey85: 253,
1021
- grey89: 254,
1022
- grey93: 255,
1023
- });
1024
- /**
1025
- * Every word `ColorSpec.parse` accepts as a name rather than a `#hex`,
1026
- * `rgb()` or `color(N)` form: `default` and the named palette entries, which
1027
- * are exactly the two name checks `parseSingle` makes.
1028
- */
1029
- export const COLOR_NAMES = ["default", ...Object.keys(ANSI_COLOR_NAMES)];