@promptctl/rich-js 0.1.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.
- package/README.md +418 -0
- package/dist/core/box.d.ts +91 -0
- package/dist/core/box.d.ts.map +1 -0
- package/dist/core/box.js +534 -0
- package/dist/core/box.js.map +1 -0
- package/dist/core/cells.d.ts +24 -0
- package/dist/core/cells.d.ts.map +1 -0
- package/dist/core/cells.js +114 -0
- package/dist/core/cells.js.map +1 -0
- package/dist/core/color.d.ts +158 -0
- package/dist/core/color.d.ts.map +1 -0
- package/dist/core/color.js +825 -0
- package/dist/core/color.js.map +1 -0
- package/dist/core/console.d.ts +100 -0
- package/dist/core/console.d.ts.map +1 -0
- package/dist/core/console.js +353 -0
- package/dist/core/console.js.map +1 -0
- package/dist/core/emoji.d.ts +25 -0
- package/dist/core/emoji.d.ts.map +1 -0
- package/dist/core/emoji.js +392 -0
- package/dist/core/emoji.js.map +1 -0
- package/dist/core/highlighter.d.ts +33 -0
- package/dist/core/highlighter.d.ts.map +1 -0
- package/dist/core/highlighter.js +103 -0
- package/dist/core/highlighter.js.map +1 -0
- package/dist/core/markup.d.ts +69 -0
- package/dist/core/markup.d.ts.map +1 -0
- package/dist/core/markup.js +401 -0
- package/dist/core/markup.js.map +1 -0
- package/dist/core/measure.d.ts +17 -0
- package/dist/core/measure.d.ts.map +1 -0
- package/dist/core/measure.js +50 -0
- package/dist/core/measure.js.map +1 -0
- package/dist/core/protocol.d.ts +32 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/protocol.js +17 -0
- package/dist/core/protocol.js.map +1 -0
- package/dist/core/render.d.ts +51 -0
- package/dist/core/render.d.ts.map +1 -0
- package/dist/core/render.js +69 -0
- package/dist/core/render.js.map +1 -0
- package/dist/core/segment.d.ts +104 -0
- package/dist/core/segment.d.ts.map +1 -0
- package/dist/core/segment.js +364 -0
- package/dist/core/segment.js.map +1 -0
- package/dist/core/spinnerData.d.ts +11 -0
- package/dist/core/spinnerData.d.ts.map +1 -0
- package/dist/core/spinnerData.js +116 -0
- package/dist/core/spinnerData.js.map +1 -0
- package/dist/core/strip.d.ts +159 -0
- package/dist/core/strip.d.ts.map +1 -0
- package/dist/core/strip.js +237 -0
- package/dist/core/strip.js.map +1 -0
- package/dist/core/style.d.ts +115 -0
- package/dist/core/style.d.ts.map +1 -0
- package/dist/core/style.js +662 -0
- package/dist/core/style.js.map +1 -0
- package/dist/core/text.d.ts +91 -0
- package/dist/core/text.d.ts.map +1 -0
- package/dist/core/text.js +610 -0
- package/dist/core/text.js.map +1 -0
- package/dist/index.d.ts +99 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +72 -0
- package/dist/index.js.map +1 -0
- package/dist/renderables/align.d.ts +17 -0
- package/dist/renderables/align.d.ts.map +1 -0
- package/dist/renderables/align.js +47 -0
- package/dist/renderables/align.js.map +1 -0
- package/dist/renderables/columns.d.ts +28 -0
- package/dist/renderables/columns.d.ts.map +1 -0
- package/dist/renderables/columns.js +92 -0
- package/dist/renderables/columns.js.map +1 -0
- package/dist/renderables/constrain.d.ts +16 -0
- package/dist/renderables/constrain.d.ts.map +1 -0
- package/dist/renderables/constrain.js +38 -0
- package/dist/renderables/constrain.js.map +1 -0
- package/dist/renderables/flexStrip.d.ts +42 -0
- package/dist/renderables/flexStrip.d.ts.map +1 -0
- package/dist/renderables/flexStrip.js +201 -0
- package/dist/renderables/flexStrip.js.map +1 -0
- package/dist/renderables/group.d.ts +12 -0
- package/dist/renderables/group.d.ts.map +1 -0
- package/dist/renderables/group.js +16 -0
- package/dist/renderables/group.js.map +1 -0
- package/dist/renderables/json.d.ts +23 -0
- package/dist/renderables/json.d.ts.map +1 -0
- package/dist/renderables/json.js +49 -0
- package/dist/renderables/json.js.map +1 -0
- package/dist/renderables/layout.d.ts +37 -0
- package/dist/renderables/layout.d.ts.map +1 -0
- package/dist/renderables/layout.js +151 -0
- package/dist/renderables/layout.js.map +1 -0
- package/dist/renderables/live.d.ts +48 -0
- package/dist/renderables/live.d.ts.map +1 -0
- package/dist/renderables/live.js +131 -0
- package/dist/renderables/live.js.map +1 -0
- package/dist/renderables/markdown.d.ts +25 -0
- package/dist/renderables/markdown.d.ts.map +1 -0
- package/dist/renderables/markdown.js +190 -0
- package/dist/renderables/markdown.js.map +1 -0
- package/dist/renderables/padding.d.ts +26 -0
- package/dist/renderables/padding.d.ts.map +1 -0
- package/dist/renderables/padding.js +92 -0
- package/dist/renderables/padding.js.map +1 -0
- package/dist/renderables/panel.d.ts +42 -0
- package/dist/renderables/panel.d.ts.map +1 -0
- package/dist/renderables/panel.js +202 -0
- package/dist/renderables/panel.js.map +1 -0
- package/dist/renderables/pretty.d.ts +29 -0
- package/dist/renderables/pretty.d.ts.map +1 -0
- package/dist/renderables/pretty.js +141 -0
- package/dist/renderables/pretty.js.map +1 -0
- package/dist/renderables/progress.d.ts +91 -0
- package/dist/renderables/progress.d.ts.map +1 -0
- package/dist/renderables/progress.js +234 -0
- package/dist/renderables/progress.js.map +1 -0
- package/dist/renderables/progressBar.d.ts +32 -0
- package/dist/renderables/progressBar.d.ts.map +1 -0
- package/dist/renderables/progressBar.js +59 -0
- package/dist/renderables/progressBar.js.map +1 -0
- package/dist/renderables/prompt.d.ts +25 -0
- package/dist/renderables/prompt.d.ts.map +1 -0
- package/dist/renderables/prompt.js +109 -0
- package/dist/renderables/prompt.js.map +1 -0
- package/dist/renderables/rule.d.ts +25 -0
- package/dist/renderables/rule.d.ts.map +1 -0
- package/dist/renderables/rule.js +96 -0
- package/dist/renderables/rule.js.map +1 -0
- package/dist/renderables/spinner.d.ts +30 -0
- package/dist/renderables/spinner.d.ts.map +1 -0
- package/dist/renderables/spinner.js +70 -0
- package/dist/renderables/spinner.js.map +1 -0
- package/dist/renderables/status.d.ts +24 -0
- package/dist/renderables/status.d.ts.map +1 -0
- package/dist/renderables/status.js +67 -0
- package/dist/renderables/status.js.map +1 -0
- package/dist/renderables/syntax.d.ts +36 -0
- package/dist/renderables/syntax.d.ts.map +1 -0
- package/dist/renderables/syntax.js +115 -0
- package/dist/renderables/syntax.js.map +1 -0
- package/dist/renderables/table.d.ts +109 -0
- package/dist/renderables/table.d.ts.map +1 -0
- package/dist/renderables/table.js +434 -0
- package/dist/renderables/table.js.map +1 -0
- package/dist/renderables/traceback.d.ts +26 -0
- package/dist/renderables/traceback.d.ts.map +1 -0
- package/dist/renderables/traceback.js +108 -0
- package/dist/renderables/traceback.js.map +1 -0
- package/dist/renderables/tree.d.ts +30 -0
- package/dist/renderables/tree.d.ts.map +1 -0
- package/dist/renderables/tree.js +107 -0
- package/dist/renderables/tree.js.map +1 -0
- package/dist/template-bindings/index.d.ts +61 -0
- package/dist/template-bindings/index.d.ts.map +1 -0
- package/dist/template-bindings/index.js +70 -0
- package/dist/template-bindings/index.js.map +1 -0
- package/dist/template-bindings/style-funcs.d.ts +30 -0
- package/dist/template-bindings/style-funcs.d.ts.map +1 -0
- package/dist/template-bindings/style-funcs.js +172 -0
- package/dist/template-bindings/style-funcs.js.map +1 -0
- package/dist/themes/buildPalette.d.ts +31 -0
- package/dist/themes/buildPalette.d.ts.map +1 -0
- package/dist/themes/buildPalette.js +43 -0
- package/dist/themes/buildPalette.js.map +1 -0
- package/dist/themes/colorMath.d.ts +23 -0
- package/dist/themes/colorMath.d.ts.map +1 -0
- package/dist/themes/colorMath.js +99 -0
- package/dist/themes/colorMath.js.map +1 -0
- package/dist/themes/data/atom-one-dark.d.ts +4 -0
- package/dist/themes/data/atom-one-dark.d.ts.map +1 -0
- package/dist/themes/data/atom-one-dark.js +159 -0
- package/dist/themes/data/atom-one-dark.js.map +1 -0
- package/dist/themes/data/atom-one-light.d.ts +4 -0
- package/dist/themes/data/atom-one-light.d.ts.map +1 -0
- package/dist/themes/data/atom-one-light.js +159 -0
- package/dist/themes/data/atom-one-light.js.map +1 -0
- package/dist/themes/data/catppuccin-latte.d.ts +4 -0
- package/dist/themes/data/catppuccin-latte.d.ts.map +1 -0
- package/dist/themes/data/catppuccin-latte.js +159 -0
- package/dist/themes/data/catppuccin-latte.js.map +1 -0
- package/dist/themes/data/catppuccin-mocha.d.ts +4 -0
- package/dist/themes/data/catppuccin-mocha.d.ts.map +1 -0
- package/dist/themes/data/catppuccin-mocha.js +159 -0
- package/dist/themes/data/catppuccin-mocha.js.map +1 -0
- package/dist/themes/data/dracula.d.ts +4 -0
- package/dist/themes/data/dracula.d.ts.map +1 -0
- package/dist/themes/data/dracula.js +159 -0
- package/dist/themes/data/dracula.js.map +1 -0
- package/dist/themes/data/flexoki.d.ts +4 -0
- package/dist/themes/data/flexoki.d.ts.map +1 -0
- package/dist/themes/data/flexoki.js +159 -0
- package/dist/themes/data/flexoki.js.map +1 -0
- package/dist/themes/data/gruvbox.d.ts +4 -0
- package/dist/themes/data/gruvbox.d.ts.map +1 -0
- package/dist/themes/data/gruvbox.js +159 -0
- package/dist/themes/data/gruvbox.js.map +1 -0
- package/dist/themes/data/index.d.ts +29 -0
- package/dist/themes/data/index.d.ts.map +1 -0
- package/dist/themes/data/index.js +48 -0
- package/dist/themes/data/index.js.map +1 -0
- package/dist/themes/data/monokai.d.ts +4 -0
- package/dist/themes/data/monokai.d.ts.map +1 -0
- package/dist/themes/data/monokai.js +159 -0
- package/dist/themes/data/monokai.js.map +1 -0
- package/dist/themes/data/nord.d.ts +4 -0
- package/dist/themes/data/nord.d.ts.map +1 -0
- package/dist/themes/data/nord.js +159 -0
- package/dist/themes/data/nord.js.map +1 -0
- package/dist/themes/data/rose-pine-dawn.d.ts +4 -0
- package/dist/themes/data/rose-pine-dawn.d.ts.map +1 -0
- package/dist/themes/data/rose-pine-dawn.js +159 -0
- package/dist/themes/data/rose-pine-dawn.js.map +1 -0
- package/dist/themes/data/rose-pine-moon.d.ts +4 -0
- package/dist/themes/data/rose-pine-moon.d.ts.map +1 -0
- package/dist/themes/data/rose-pine-moon.js +159 -0
- package/dist/themes/data/rose-pine-moon.js.map +1 -0
- package/dist/themes/data/rose-pine.d.ts +4 -0
- package/dist/themes/data/rose-pine.d.ts.map +1 -0
- package/dist/themes/data/rose-pine.js +159 -0
- package/dist/themes/data/rose-pine.js.map +1 -0
- package/dist/themes/data/solarized-dark.d.ts +4 -0
- package/dist/themes/data/solarized-dark.d.ts.map +1 -0
- package/dist/themes/data/solarized-dark.js +159 -0
- package/dist/themes/data/solarized-dark.js.map +1 -0
- package/dist/themes/data/solarized-light.d.ts +4 -0
- package/dist/themes/data/solarized-light.d.ts.map +1 -0
- package/dist/themes/data/solarized-light.js +159 -0
- package/dist/themes/data/solarized-light.js.map +1 -0
- package/dist/themes/data/textual-ansi.d.ts +4 -0
- package/dist/themes/data/textual-ansi.d.ts.map +1 -0
- package/dist/themes/data/textual-ansi.js +159 -0
- package/dist/themes/data/textual-ansi.js.map +1 -0
- package/dist/themes/data/textual-dark.d.ts +4 -0
- package/dist/themes/data/textual-dark.d.ts.map +1 -0
- package/dist/themes/data/textual-dark.js +159 -0
- package/dist/themes/data/textual-dark.js.map +1 -0
- package/dist/themes/data/textual-light.d.ts +4 -0
- package/dist/themes/data/textual-light.d.ts.map +1 -0
- package/dist/themes/data/textual-light.js +159 -0
- package/dist/themes/data/textual-light.js.map +1 -0
- package/dist/themes/data/tokyo-night.d.ts +4 -0
- package/dist/themes/data/tokyo-night.d.ts.map +1 -0
- package/dist/themes/data/tokyo-night.js +159 -0
- package/dist/themes/data/tokyo-night.js.map +1 -0
- package/dist/themes/data/types.d.ts +15 -0
- package/dist/themes/data/types.d.ts.map +1 -0
- package/dist/themes/data/types.js +2 -0
- package/dist/themes/data/types.js.map +1 -0
- package/dist/themes/palette.d.ts +20 -0
- package/dist/themes/palette.d.ts.map +1 -0
- package/dist/themes/palette.js +27 -0
- package/dist/themes/palette.js.map +1 -0
- package/dist/themes/paletteResolver.d.ts +35 -0
- package/dist/themes/paletteResolver.d.ts.map +1 -0
- package/dist/themes/paletteResolver.js +88 -0
- package/dist/themes/paletteResolver.js.map +1 -0
- package/dist/themes/registry.d.ts +17 -0
- package/dist/themes/registry.d.ts.map +1 -0
- package/dist/themes/registry.js +33 -0
- package/dist/themes/registry.js.map +1 -0
- package/dist/themes/terminalThemes.d.ts +46 -0
- package/dist/themes/terminalThemes.d.ts.map +1 -0
- package/dist/themes/terminalThemes.js +268 -0
- package/dist/themes/terminalThemes.js.map +1 -0
- package/dist/widgets/button.d.ts +47 -0
- package/dist/widgets/button.d.ts.map +1 -0
- package/dist/widgets/button.js +183 -0
- package/dist/widgets/button.js.map +1 -0
- package/dist/widgets/checkbox.d.ts +43 -0
- package/dist/widgets/checkbox.d.ts.map +1 -0
- package/dist/widgets/checkbox.js +144 -0
- package/dist/widgets/checkbox.js.map +1 -0
- package/dist/widgets/dropdown.d.ts +67 -0
- package/dist/widgets/dropdown.d.ts.map +1 -0
- package/dist/widgets/dropdown.js +373 -0
- package/dist/widgets/dropdown.js.map +1 -0
- package/dist/widgets/event-router.d.ts +73 -0
- package/dist/widgets/event-router.d.ts.map +1 -0
- package/dist/widgets/event-router.js +479 -0
- package/dist/widgets/event-router.js.map +1 -0
- package/dist/widgets/focus-manager.d.ts +26 -0
- package/dist/widgets/focus-manager.d.ts.map +1 -0
- package/dist/widgets/focus-manager.js +179 -0
- package/dist/widgets/focus-manager.js.map +1 -0
- package/dist/widgets/index.d.ts +23 -0
- package/dist/widgets/index.d.ts.map +1 -0
- package/dist/widgets/index.js +13 -0
- package/dist/widgets/index.js.map +1 -0
- package/dist/widgets/screen.d.ts +90 -0
- package/dist/widgets/screen.d.ts.map +1 -0
- package/dist/widgets/screen.js +440 -0
- package/dist/widgets/screen.js.map +1 -0
- package/dist/widgets/slider.d.ts +55 -0
- package/dist/widgets/slider.d.ts.map +1 -0
- package/dist/widgets/slider.js +248 -0
- package/dist/widgets/slider.js.map +1 -0
- package/dist/widgets/static-item.d.ts +41 -0
- package/dist/widgets/static-item.d.ts.map +1 -0
- package/dist/widgets/static-item.js +62 -0
- package/dist/widgets/static-item.js.map +1 -0
- package/dist/widgets/text-input.d.ts +50 -0
- package/dist/widgets/text-input.d.ts.map +1 -0
- package/dist/widgets/text-input.js +242 -0
- package/dist/widgets/text-input.js.map +1 -0
- package/dist/widgets/toggle.d.ts +46 -0
- package/dist/widgets/toggle.d.ts.map +1 -0
- package/dist/widgets/toggle.js +169 -0
- package/dist/widgets/toggle.js.map +1 -0
- package/dist/widgets/types.d.ts +92 -0
- package/dist/widgets/types.d.ts.map +1 -0
- package/dist/widgets/types.js +13 -0
- package/dist/widgets/types.js.map +1 -0
- package/dist/widgets/widget-base.d.ts +41 -0
- package/dist/widgets/widget-base.d.ts.map +1 -0
- package/dist/widgets/widget-base.js +159 -0
- package/dist/widgets/widget-base.js.map +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,825 @@
|
|
|
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
|
+
// --- ColorTable ---
|
|
69
|
+
export class ColorTable {
|
|
70
|
+
colors;
|
|
71
|
+
matchCache = new Map();
|
|
72
|
+
constructor(colors) {
|
|
73
|
+
this.colors = colors;
|
|
74
|
+
}
|
|
75
|
+
get(index) {
|
|
76
|
+
return this.colors[index];
|
|
77
|
+
}
|
|
78
|
+
get size() {
|
|
79
|
+
return this.colors.length;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Finds the nearest table index to the given color (Euclidean RGB distance, cached).
|
|
83
|
+
* Alpha is part of the cache key so two values that differ only in alpha
|
|
84
|
+
* don't collide, but is not used in the distance metric.
|
|
85
|
+
*/
|
|
86
|
+
match(value) {
|
|
87
|
+
const key = `${value.red},${value.green},${value.blue},${value.alpha}`;
|
|
88
|
+
const cached = this.matchCache.get(key);
|
|
89
|
+
if (cached !== undefined)
|
|
90
|
+
return cached;
|
|
91
|
+
let bestIndex = 0;
|
|
92
|
+
let bestDist = Infinity;
|
|
93
|
+
for (let i = 0; i < this.colors.length; i++) {
|
|
94
|
+
const c = this.colors[i];
|
|
95
|
+
const dr = c.red - value.red;
|
|
96
|
+
const dg = c.green - value.green;
|
|
97
|
+
const db = c.blue - value.blue;
|
|
98
|
+
const dist = dr * dr + dg * dg + db * db;
|
|
99
|
+
if (dist < bestDist) {
|
|
100
|
+
bestDist = dist;
|
|
101
|
+
bestIndex = i;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
this.matchCache.set(key, bestIndex);
|
|
105
|
+
return bestIndex;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// --- Enums ---
|
|
109
|
+
export var ColorDepth;
|
|
110
|
+
(function (ColorDepth) {
|
|
111
|
+
ColorDepth[ColorDepth["DEFAULT"] = 0] = "DEFAULT";
|
|
112
|
+
ColorDepth[ColorDepth["STANDARD"] = 1] = "STANDARD";
|
|
113
|
+
ColorDepth[ColorDepth["EIGHT_BIT"] = 2] = "EIGHT_BIT";
|
|
114
|
+
ColorDepth[ColorDepth["TRUECOLOR"] = 3] = "TRUECOLOR";
|
|
115
|
+
ColorDepth[ColorDepth["WINDOWS"] = 4] = "WINDOWS";
|
|
116
|
+
})(ColorDepth || (ColorDepth = {}));
|
|
117
|
+
// [LAW:one-source-of-truth] One table covers every recognized string form
|
|
118
|
+
// that resolves to a ColorDepth: user-facing CLI/config specs, FORCE_COLOR
|
|
119
|
+
// values (the chalk/supports-color convention), TERM_PROGRAM identifiers,
|
|
120
|
+
// and exact TERM names whose color capability is known. Keys are disjoint
|
|
121
|
+
// across these sources, so one table is honest. `null` means "no color".
|
|
122
|
+
// "auto" is intentionally absent — it routes to env detection.
|
|
123
|
+
const STRING_TO_DEPTH = {
|
|
124
|
+
// CLI/config specs
|
|
125
|
+
truecolor: ColorDepth.TRUECOLOR,
|
|
126
|
+
"256": ColorDepth.EIGHT_BIT,
|
|
127
|
+
ansi: ColorDepth.STANDARD,
|
|
128
|
+
none: null,
|
|
129
|
+
// FORCE_COLOR values
|
|
130
|
+
"0": null,
|
|
131
|
+
false: null,
|
|
132
|
+
"1": ColorDepth.STANDARD,
|
|
133
|
+
true: ColorDepth.STANDARD,
|
|
134
|
+
"2": ColorDepth.EIGHT_BIT,
|
|
135
|
+
"3": ColorDepth.TRUECOLOR,
|
|
136
|
+
// TERM_PROGRAM identifiers
|
|
137
|
+
"iTerm.app": ColorDepth.TRUECOLOR,
|
|
138
|
+
Apple_Terminal: ColorDepth.EIGHT_BIT,
|
|
139
|
+
vscode: ColorDepth.TRUECOLOR,
|
|
140
|
+
Tabby: ColorDepth.TRUECOLOR,
|
|
141
|
+
// Known truecolor TERM names
|
|
142
|
+
"xterm-kitty": ColorDepth.TRUECOLOR,
|
|
143
|
+
"xterm-ghostty": ColorDepth.TRUECOLOR,
|
|
144
|
+
wezterm: ColorDepth.TRUECOLOR,
|
|
145
|
+
alacritty: ColorDepth.TRUECOLOR,
|
|
146
|
+
foot: ColorDepth.TRUECOLOR,
|
|
147
|
+
contour: ColorDepth.TRUECOLOR,
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Detect the terminal's color capability from env + TTY state.
|
|
151
|
+
*
|
|
152
|
+
* Probes (in priority order): NO_COLOR (per https://no-color.org —
|
|
153
|
+
* any non-empty value disables color), FORCE_COLOR (numeric/boolean override),
|
|
154
|
+
* TTY presence, TERM=dumb/unknown, COLORTERM, known terminal/TERM_PROGRAM
|
|
155
|
+
* names, and TERM regex patterns. Returns `null` for "no color".
|
|
156
|
+
*
|
|
157
|
+
* [LAW:dataflow-not-control-flow] Same probes run every call; variability is
|
|
158
|
+
* in the env values, not in which checks execute.
|
|
159
|
+
*/
|
|
160
|
+
export function detectColorSystem(options = {}) {
|
|
161
|
+
const env = options.env ?? (typeof process !== "undefined" ? process.env : {});
|
|
162
|
+
const isTTY = options.isTTY ??
|
|
163
|
+
(typeof process !== "undefined" ? (process.stdout?.isTTY ?? false) : false);
|
|
164
|
+
// NO_COLOR: any non-empty value disables color.
|
|
165
|
+
const noColor = env["NO_COLOR"];
|
|
166
|
+
if (noColor !== undefined && noColor !== "")
|
|
167
|
+
return null;
|
|
168
|
+
// FORCE_COLOR: explicit override, wins over TTY/TERM detection.
|
|
169
|
+
const force = env["FORCE_COLOR"];
|
|
170
|
+
if (force !== undefined && force !== "") {
|
|
171
|
+
const mapped = STRING_TO_DEPTH[force];
|
|
172
|
+
return mapped !== undefined ? mapped : ColorDepth.STANDARD;
|
|
173
|
+
}
|
|
174
|
+
if (!isTTY)
|
|
175
|
+
return null;
|
|
176
|
+
const term = env["TERM"] ?? "";
|
|
177
|
+
if (term === "dumb" || term === "unknown")
|
|
178
|
+
return null;
|
|
179
|
+
const colorterm = env["COLORTERM"];
|
|
180
|
+
if (colorterm === "truecolor" || colorterm === "24bit") {
|
|
181
|
+
return ColorDepth.TRUECOLOR;
|
|
182
|
+
}
|
|
183
|
+
const termDepth = STRING_TO_DEPTH[term];
|
|
184
|
+
if (termDepth !== undefined)
|
|
185
|
+
return termDepth;
|
|
186
|
+
const termProgram = env["TERM_PROGRAM"];
|
|
187
|
+
if (termProgram !== undefined) {
|
|
188
|
+
const mapped = STRING_TO_DEPTH[termProgram];
|
|
189
|
+
if (mapped !== undefined)
|
|
190
|
+
return mapped;
|
|
191
|
+
}
|
|
192
|
+
if (/-256(color)?$/i.test(term))
|
|
193
|
+
return ColorDepth.EIGHT_BIT;
|
|
194
|
+
if (/-truecolor$/i.test(term))
|
|
195
|
+
return ColorDepth.TRUECOLOR;
|
|
196
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(term)) {
|
|
197
|
+
return ColorDepth.STANDARD;
|
|
198
|
+
}
|
|
199
|
+
if (colorterm !== undefined && colorterm !== "")
|
|
200
|
+
return ColorDepth.STANDARD;
|
|
201
|
+
// Default: a terminal exists (isTTY=true) but we couldn't classify it.
|
|
202
|
+
// Assume safe baseline rather than disabling color.
|
|
203
|
+
return ColorDepth.STANDARD;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Resolve a string spec into a `ColorDepth` (or `null` for no color).
|
|
207
|
+
*
|
|
208
|
+
* `"auto"` triggers env-based detection; all other recognized specs are
|
|
209
|
+
* direct table lookups against `STRING_TO_DEPTH`. Throws on unknown specs
|
|
210
|
+
* — silent fallback would mask user typos.
|
|
211
|
+
*
|
|
212
|
+
* [LAW:single-enforcer] All string→ColorDepth resolution flows through here.
|
|
213
|
+
*/
|
|
214
|
+
export function resolveColorSystem(spec, options) {
|
|
215
|
+
if (spec === "auto")
|
|
216
|
+
return detectColorSystem(options);
|
|
217
|
+
if (Object.hasOwn(STRING_TO_DEPTH, spec))
|
|
218
|
+
return STRING_TO_DEPTH[spec];
|
|
219
|
+
throw new ColorParseError(`Unknown color depth spec: ${JSON.stringify(spec)} (expected "auto", "truecolor", "256", "ansi", or "none")`);
|
|
220
|
+
}
|
|
221
|
+
// --- ColorSpec ---
|
|
222
|
+
export class ColorParseError extends Error {
|
|
223
|
+
constructor(message) {
|
|
224
|
+
super(message);
|
|
225
|
+
this.name = "ColorParseError";
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// [LAW:one-source-of-truth] Parse cache is the single source for parsed ColorSpec instances
|
|
229
|
+
const parseCache = new Map();
|
|
230
|
+
export class ColorSpec {
|
|
231
|
+
name;
|
|
232
|
+
type;
|
|
233
|
+
number;
|
|
234
|
+
value;
|
|
235
|
+
downgradeCache = new Map();
|
|
236
|
+
constructor(name, type, number, value) {
|
|
237
|
+
this.name = name;
|
|
238
|
+
this.type = type;
|
|
239
|
+
this.number = number;
|
|
240
|
+
this.value = value;
|
|
241
|
+
}
|
|
242
|
+
get isDefault() {
|
|
243
|
+
return this.type === ColorDepth.DEFAULT;
|
|
244
|
+
}
|
|
245
|
+
get isSystemDefined() {
|
|
246
|
+
return (this.type === ColorDepth.STANDARD || this.type === ColorDepth.WINDOWS);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Generates SGR parameter strings for this color.
|
|
250
|
+
*/
|
|
251
|
+
getAnsiCodes(foreground = true) {
|
|
252
|
+
switch (this.type) {
|
|
253
|
+
case ColorDepth.DEFAULT:
|
|
254
|
+
return [foreground ? "39" : "49"];
|
|
255
|
+
case ColorDepth.STANDARD: {
|
|
256
|
+
const n = this.number;
|
|
257
|
+
if (foreground) {
|
|
258
|
+
return n < 8 ? [`${30 + n}`] : [`${90 + n - 8}`];
|
|
259
|
+
}
|
|
260
|
+
return n < 8 ? [`${40 + n}`] : [`${100 + n - 8}`];
|
|
261
|
+
}
|
|
262
|
+
case ColorDepth.EIGHT_BIT:
|
|
263
|
+
return [foreground ? "38" : "48", "5", `${this.number}`];
|
|
264
|
+
case ColorDepth.TRUECOLOR: {
|
|
265
|
+
const t = this.value;
|
|
266
|
+
return [
|
|
267
|
+
foreground ? "38" : "48",
|
|
268
|
+
"2",
|
|
269
|
+
`${t.red}`,
|
|
270
|
+
`${t.green}`,
|
|
271
|
+
`${t.blue}`,
|
|
272
|
+
];
|
|
273
|
+
}
|
|
274
|
+
case ColorDepth.WINDOWS: {
|
|
275
|
+
const n = this.number;
|
|
276
|
+
if (foreground) {
|
|
277
|
+
return n < 8 ? [`${30 + n}`] : [`${90 + n - 8}`];
|
|
278
|
+
}
|
|
279
|
+
return n < 8 ? [`${40 + n}`] : [`${100 + n - 8}`];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Composite this color's alpha (if any) against an opaque background,
|
|
285
|
+
* returning a fully-opaque ColorSpec. Non-truecolor specs (palette
|
|
286
|
+
* indices, default) have no alpha and pass through unchanged.
|
|
287
|
+
*
|
|
288
|
+
* [LAW:single-enforcer] Sole alpha-flattening site for the render
|
|
289
|
+
* pipeline. Run *before* downgrade — otherwise palette matching on the
|
|
290
|
+
* still-translucent RGB silently drops alpha (the "flatten then lose
|
|
291
|
+
* alpha" path the unification ticket forbids).
|
|
292
|
+
*
|
|
293
|
+
* [LAW:dataflow-not-control-flow] `ColorRgba.compositeOver` is a no-op
|
|
294
|
+
* when alpha=1, so callers invoke this unconditionally; the data
|
|
295
|
+
* (alpha value) decides whether work happens.
|
|
296
|
+
*/
|
|
297
|
+
flattenAlpha(bg) {
|
|
298
|
+
if (this.type !== ColorDepth.TRUECOLOR || !this.value)
|
|
299
|
+
return this;
|
|
300
|
+
const flat = this.value.compositeOver(bg);
|
|
301
|
+
return flat === this.value ? this : ColorSpec.fromRgba(flat);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Downgrade to a lower-fidelity color depth. Cached.
|
|
305
|
+
*/
|
|
306
|
+
downgrade(targetSystem) {
|
|
307
|
+
if (this.type === ColorDepth.DEFAULT)
|
|
308
|
+
return this;
|
|
309
|
+
if (this.type <= targetSystem)
|
|
310
|
+
return this;
|
|
311
|
+
const cached = this.downgradeCache.get(targetSystem);
|
|
312
|
+
if (cached)
|
|
313
|
+
return cached;
|
|
314
|
+
const result = this.performDowngrade(targetSystem);
|
|
315
|
+
this.downgradeCache.set(targetSystem, result);
|
|
316
|
+
return result;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Resolves to an actual RGB(A) value for any color type.
|
|
320
|
+
*/
|
|
321
|
+
getTruecolor(theme, foreground = true) {
|
|
322
|
+
switch (this.type) {
|
|
323
|
+
case ColorDepth.TRUECOLOR:
|
|
324
|
+
return this.value;
|
|
325
|
+
case ColorDepth.EIGHT_BIT:
|
|
326
|
+
return EIGHT_BIT_TABLE.get(this.number);
|
|
327
|
+
case ColorDepth.STANDARD: {
|
|
328
|
+
const t = theme ?? INTERNAL_DEFAULT_THEME;
|
|
329
|
+
return t.ansiColors.get(this.number);
|
|
330
|
+
}
|
|
331
|
+
case ColorDepth.DEFAULT: {
|
|
332
|
+
const t = theme ?? INTERNAL_DEFAULT_THEME;
|
|
333
|
+
return foreground ? t.foregroundColor : t.backgroundColor;
|
|
334
|
+
}
|
|
335
|
+
case ColorDepth.WINDOWS: {
|
|
336
|
+
const t = theme ?? INTERNAL_DEFAULT_THEME;
|
|
337
|
+
return t.ansiColors.get(this.number);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
// --- Static factories ---
|
|
342
|
+
static default() {
|
|
343
|
+
return new ColorSpec("default", ColorDepth.DEFAULT);
|
|
344
|
+
}
|
|
345
|
+
static fromAnsi(n) {
|
|
346
|
+
const type = n < 16 ? ColorDepth.STANDARD : ColorDepth.EIGHT_BIT;
|
|
347
|
+
return new ColorSpec(`color(${n})`, type, n);
|
|
348
|
+
}
|
|
349
|
+
static fromRgba(value) {
|
|
350
|
+
return new ColorSpec(value.hex, ColorDepth.TRUECOLOR, undefined, value);
|
|
351
|
+
}
|
|
352
|
+
static fromRgb(r, g, b) {
|
|
353
|
+
return ColorSpec.fromRgba(new ColorRgba(r, g, b));
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Parse a color string. Cached — identical strings return the same instance.
|
|
357
|
+
*/
|
|
358
|
+
static parse(colorString) {
|
|
359
|
+
const key = colorString.toLowerCase().trim();
|
|
360
|
+
const cached = parseCache.get(key);
|
|
361
|
+
if (cached)
|
|
362
|
+
return cached;
|
|
363
|
+
const result = parseSingle(key);
|
|
364
|
+
parseCache.set(key, result);
|
|
365
|
+
return result;
|
|
366
|
+
}
|
|
367
|
+
// --- private ---
|
|
368
|
+
performDowngrade(targetSystem) {
|
|
369
|
+
// Get the true RGB of this color
|
|
370
|
+
const triplet = this.getTruecolor();
|
|
371
|
+
switch (targetSystem) {
|
|
372
|
+
case ColorDepth.EIGHT_BIT: {
|
|
373
|
+
const index = EIGHT_BIT_TABLE.match(triplet);
|
|
374
|
+
return ColorSpec.fromAnsi(index);
|
|
375
|
+
}
|
|
376
|
+
case ColorDepth.STANDARD: {
|
|
377
|
+
const index = STANDARD_TABLE.match(triplet);
|
|
378
|
+
return new ColorSpec(`color(${index})`, ColorDepth.STANDARD, index);
|
|
379
|
+
}
|
|
380
|
+
// WINDOWS is a detection result (max enum value), not a downgrade target.
|
|
381
|
+
// The `this.type <= targetSystem` guard in downgrade() always short-circuits
|
|
382
|
+
// before reaching this method with WINDOWS, so this case is unreachable.
|
|
383
|
+
case ColorDepth.WINDOWS:
|
|
384
|
+
case ColorDepth.TRUECOLOR:
|
|
385
|
+
return this;
|
|
386
|
+
case ColorDepth.DEFAULT:
|
|
387
|
+
return ColorSpec.default();
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
// --- Parsing internals ---
|
|
392
|
+
const HEX_RE = /^#([0-9a-f]{6})$/;
|
|
393
|
+
const HEX_RGBA_RE = /^#([0-9a-f]{8})$/;
|
|
394
|
+
const RGB_RE = /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/;
|
|
395
|
+
const COLOR_NUMBER_RE = /^color\((\d{1,3})\)$/;
|
|
396
|
+
function parseSingle(key) {
|
|
397
|
+
if (key === "default" || key === "") {
|
|
398
|
+
return ColorSpec.default();
|
|
399
|
+
}
|
|
400
|
+
// Named color
|
|
401
|
+
const namedIndex = ANSI_COLOR_NAMES[key];
|
|
402
|
+
if (namedIndex !== undefined) {
|
|
403
|
+
const type = namedIndex < 16 ? ColorDepth.STANDARD : ColorDepth.EIGHT_BIT;
|
|
404
|
+
return new ColorSpec(key, type, namedIndex);
|
|
405
|
+
}
|
|
406
|
+
// Hex (8-char with alpha takes precedence over 6-char to avoid the 6-char
|
|
407
|
+
// regex matching a prefix of an 8-char string).
|
|
408
|
+
const hexRgbaMatch = HEX_RGBA_RE.exec(key);
|
|
409
|
+
if (hexRgbaMatch) {
|
|
410
|
+
return new ColorSpec(key, ColorDepth.TRUECOLOR, undefined, parseRgbaHex(hexRgbaMatch[1]));
|
|
411
|
+
}
|
|
412
|
+
const hexMatch = HEX_RE.exec(key);
|
|
413
|
+
if (hexMatch) {
|
|
414
|
+
return new ColorSpec(key, ColorDepth.TRUECOLOR, undefined, parseRgbHex(hexMatch[1]));
|
|
415
|
+
}
|
|
416
|
+
// rgb()
|
|
417
|
+
const rgbMatch = RGB_RE.exec(key);
|
|
418
|
+
if (rgbMatch) {
|
|
419
|
+
const r = parseInt(rgbMatch[1], 10);
|
|
420
|
+
const g = parseInt(rgbMatch[2], 10);
|
|
421
|
+
const b = parseInt(rgbMatch[3], 10);
|
|
422
|
+
return new ColorSpec(key, ColorDepth.TRUECOLOR, undefined, new ColorRgba(r, g, b));
|
|
423
|
+
}
|
|
424
|
+
// color(N)
|
|
425
|
+
const numMatch = COLOR_NUMBER_RE.exec(key);
|
|
426
|
+
if (numMatch) {
|
|
427
|
+
const n = parseInt(numMatch[1], 10);
|
|
428
|
+
if (n > 255) {
|
|
429
|
+
throw new ColorParseError(`ColorSpec number ${n} is out of range (0-255)`);
|
|
430
|
+
}
|
|
431
|
+
const type = n < 16 ? ColorDepth.STANDARD : ColorDepth.EIGHT_BIT;
|
|
432
|
+
return new ColorSpec(key, type, n);
|
|
433
|
+
}
|
|
434
|
+
throw new ColorParseError(`Failed to parse color: "${key}"`);
|
|
435
|
+
}
|
|
436
|
+
// --- Utility functions ---
|
|
437
|
+
export function parseRgbHex(hex) {
|
|
438
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
439
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
440
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
441
|
+
return new ColorRgba(r, g, b);
|
|
442
|
+
}
|
|
443
|
+
export function parseRgbaHex(hex) {
|
|
444
|
+
const r = parseInt(hex.slice(0, 2), 16);
|
|
445
|
+
const g = parseInt(hex.slice(2, 4), 16);
|
|
446
|
+
const b = parseInt(hex.slice(4, 6), 16);
|
|
447
|
+
const a = parseInt(hex.slice(6, 8), 16) / 255;
|
|
448
|
+
return new ColorRgba(r, g, b, a);
|
|
449
|
+
}
|
|
450
|
+
export function blendRgb(color1, color2, crossFade = 0.5) {
|
|
451
|
+
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);
|
|
452
|
+
}
|
|
453
|
+
// --- TerminalTheme ---
|
|
454
|
+
/**
|
|
455
|
+
* A terminal theme — surface/foreground baseline, the ANSI 16/256 LUT, and a
|
|
456
|
+
* semantic palette.
|
|
457
|
+
*
|
|
458
|
+
* **`ansiColors` is the canonical ANSI table, not a per-theme override.** All
|
|
459
|
+
* preset themes in this codebase use `STANDARD_TABLE` for `ansiColors`. Theme
|
|
460
|
+
* identity lives entirely in `palette` (primary, accent, text-*, surface, ...);
|
|
461
|
+
* `ColorSpec.parse("red")` is intentionally consistent across themes — same
|
|
462
|
+
* design as Textual itself, which models theming at the truecolor/semantic
|
|
463
|
+
* layer rather than overloading the ANSI 16. Custom callers building bespoke
|
|
464
|
+
* themes that *do* want to retint ANSI 16 are free to pass their own
|
|
465
|
+
* `ColorTable`; that path is supported but not how the built-in presets work.
|
|
466
|
+
*/
|
|
467
|
+
export class TerminalTheme {
|
|
468
|
+
backgroundColor;
|
|
469
|
+
foregroundColor;
|
|
470
|
+
ansiColors;
|
|
471
|
+
palette;
|
|
472
|
+
constructor(backgroundColor, foregroundColor, ansiColors, palette) {
|
|
473
|
+
this.backgroundColor = backgroundColor;
|
|
474
|
+
this.foregroundColor = foregroundColor;
|
|
475
|
+
this.ansiColors = ansiColors;
|
|
476
|
+
this.palette = palette;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// --- ColorTable data ---
|
|
480
|
+
function buildStandard16() {
|
|
481
|
+
return [
|
|
482
|
+
new ColorRgba(0, 0, 0), // 0 black
|
|
483
|
+
new ColorRgba(128, 0, 0), // 1 red
|
|
484
|
+
new ColorRgba(0, 128, 0), // 2 green
|
|
485
|
+
new ColorRgba(128, 128, 0), // 3 yellow
|
|
486
|
+
new ColorRgba(0, 0, 128), // 4 blue
|
|
487
|
+
new ColorRgba(128, 0, 128), // 5 magenta
|
|
488
|
+
new ColorRgba(0, 128, 128), // 6 cyan
|
|
489
|
+
new ColorRgba(192, 192, 192), // 7 white
|
|
490
|
+
new ColorRgba(128, 128, 128), // 8 bright_black
|
|
491
|
+
new ColorRgba(255, 0, 0), // 9 bright_red
|
|
492
|
+
new ColorRgba(0, 255, 0), // 10 bright_green
|
|
493
|
+
new ColorRgba(255, 255, 0), // 11 bright_yellow
|
|
494
|
+
new ColorRgba(0, 0, 255), // 12 bright_blue
|
|
495
|
+
new ColorRgba(255, 0, 255), // 13 bright_magenta
|
|
496
|
+
new ColorRgba(0, 255, 255), // 14 bright_cyan
|
|
497
|
+
new ColorRgba(255, 255, 255), // 15 bright_white
|
|
498
|
+
];
|
|
499
|
+
}
|
|
500
|
+
function build256Table() {
|
|
501
|
+
const colors = buildStandard16();
|
|
502
|
+
// 6x6x6 color cube (indices 16-231)
|
|
503
|
+
const levels = [0, 95, 135, 175, 215, 255];
|
|
504
|
+
for (let r = 0; r < 6; r++) {
|
|
505
|
+
for (let g = 0; g < 6; g++) {
|
|
506
|
+
for (let b = 0; b < 6; b++) {
|
|
507
|
+
colors.push(new ColorRgba(levels[r], levels[g], levels[b]));
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
// Grayscale ramp (indices 232-255)
|
|
512
|
+
for (let i = 0; i < 24; i++) {
|
|
513
|
+
const grey = 8 + 10 * i;
|
|
514
|
+
colors.push(new ColorRgba(grey, grey, grey));
|
|
515
|
+
}
|
|
516
|
+
return colors;
|
|
517
|
+
}
|
|
518
|
+
function buildWindowsTable() {
|
|
519
|
+
return [
|
|
520
|
+
new ColorRgba(0, 0, 0), // 0
|
|
521
|
+
new ColorRgba(0, 0, 128), // 1
|
|
522
|
+
new ColorRgba(0, 128, 0), // 2
|
|
523
|
+
new ColorRgba(0, 128, 128), // 3
|
|
524
|
+
new ColorRgba(128, 0, 0), // 4
|
|
525
|
+
new ColorRgba(128, 0, 128), // 5
|
|
526
|
+
new ColorRgba(128, 128, 0), // 6
|
|
527
|
+
new ColorRgba(192, 192, 192), // 7
|
|
528
|
+
new ColorRgba(128, 128, 128), // 8
|
|
529
|
+
new ColorRgba(0, 0, 255), // 9
|
|
530
|
+
new ColorRgba(0, 255, 0), // 10
|
|
531
|
+
new ColorRgba(0, 255, 255), // 11
|
|
532
|
+
new ColorRgba(255, 0, 0), // 12
|
|
533
|
+
new ColorRgba(255, 0, 255), // 13
|
|
534
|
+
new ColorRgba(255, 255, 0), // 14
|
|
535
|
+
new ColorRgba(255, 255, 255), // 15
|
|
536
|
+
];
|
|
537
|
+
}
|
|
538
|
+
export const STANDARD_TABLE = new ColorTable(buildStandard16());
|
|
539
|
+
export const EIGHT_BIT_TABLE = new ColorTable(build256Table());
|
|
540
|
+
export const WINDOWS_TABLE = new ColorTable(buildWindowsTable());
|
|
541
|
+
// --- Internal fallback theme ---
|
|
542
|
+
//
|
|
543
|
+
// [LAW:one-way-deps] Preset themes (DEFAULT_TERMINAL_THEME, MONOKAI, NORD, ...)
|
|
544
|
+
// live in `src/themes/terminalThemes.ts` because they need `buildPalette` from
|
|
545
|
+
// `themes/`. Keeping them out of `core/color.ts` makes the dependency strictly
|
|
546
|
+
// `themes/* -> core/color`, with no runtime back-edge.
|
|
547
|
+
//
|
|
548
|
+
// `getTruecolor()` retains a fallback for callers that omit `theme`. The
|
|
549
|
+
// fallback uses STANDARD_TABLE + black/white + an empty Palette — sufficient
|
|
550
|
+
// for STANDARD/DEFAULT/WINDOWS lookups, which never read `palette`.
|
|
551
|
+
//
|
|
552
|
+
// Runtime-importing `Palette` from `themes/palette.ts` is safe: that module
|
|
553
|
+
// only `import type`s from `core/color.ts`, so there is no runtime cycle.
|
|
554
|
+
import { Palette } from "../themes/palette.js";
|
|
555
|
+
const INTERNAL_DEFAULT_THEME = new TerminalTheme(new ColorRgba(0, 0, 0), new ColorRgba(255, 255, 255), STANDARD_TABLE, new Palette("default", true, new Map()));
|
|
556
|
+
// --- ANSI ColorSpec Names ---
|
|
557
|
+
// [LAW:one-source-of-truth] Single canonical mapping from name → palette index
|
|
558
|
+
export const ANSI_COLOR_NAMES = {
|
|
559
|
+
// Standard 16
|
|
560
|
+
black: 0,
|
|
561
|
+
red: 1,
|
|
562
|
+
green: 2,
|
|
563
|
+
yellow: 3,
|
|
564
|
+
blue: 4,
|
|
565
|
+
magenta: 5,
|
|
566
|
+
cyan: 6,
|
|
567
|
+
white: 7,
|
|
568
|
+
bright_black: 8,
|
|
569
|
+
bright_red: 9,
|
|
570
|
+
bright_green: 10,
|
|
571
|
+
bright_yellow: 11,
|
|
572
|
+
bright_blue: 12,
|
|
573
|
+
bright_magenta: 13,
|
|
574
|
+
bright_cyan: 14,
|
|
575
|
+
bright_white: 15,
|
|
576
|
+
// 6x6x6 color cube (16-231)
|
|
577
|
+
grey0: 16,
|
|
578
|
+
navy_blue: 17,
|
|
579
|
+
dark_blue: 18,
|
|
580
|
+
blue3: 19,
|
|
581
|
+
blue2: 20,
|
|
582
|
+
blue1: 21,
|
|
583
|
+
dark_green: 22,
|
|
584
|
+
deep_sky_blue4: 23,
|
|
585
|
+
deep_sky_blue5: 24,
|
|
586
|
+
deep_sky_blue6: 25,
|
|
587
|
+
dodger_blue3: 26,
|
|
588
|
+
dodger_blue2: 27,
|
|
589
|
+
green4: 28,
|
|
590
|
+
spring_green4: 29,
|
|
591
|
+
turquoise4: 30,
|
|
592
|
+
deep_sky_blue3: 31,
|
|
593
|
+
deep_sky_blue7: 32,
|
|
594
|
+
dodger_blue1: 33,
|
|
595
|
+
green3: 34,
|
|
596
|
+
spring_green3: 35,
|
|
597
|
+
dark_cyan: 36,
|
|
598
|
+
light_sea_green: 37,
|
|
599
|
+
deep_sky_blue2: 38,
|
|
600
|
+
deep_sky_blue1: 39,
|
|
601
|
+
green5: 40,
|
|
602
|
+
spring_green5: 41,
|
|
603
|
+
spring_green2: 42,
|
|
604
|
+
cyan3: 43,
|
|
605
|
+
dark_turquoise: 44,
|
|
606
|
+
turquoise2: 45,
|
|
607
|
+
green1: 46,
|
|
608
|
+
spring_green6: 47,
|
|
609
|
+
spring_green1: 48,
|
|
610
|
+
medium_spring_green: 49,
|
|
611
|
+
cyan2: 50,
|
|
612
|
+
cyan1: 51,
|
|
613
|
+
dark_red: 52,
|
|
614
|
+
deep_pink4: 53,
|
|
615
|
+
purple4: 54,
|
|
616
|
+
purple5: 55,
|
|
617
|
+
purple3: 56,
|
|
618
|
+
blue_violet: 57,
|
|
619
|
+
orange4: 58,
|
|
620
|
+
grey37: 59,
|
|
621
|
+
medium_purple4: 60,
|
|
622
|
+
slate_blue3: 61,
|
|
623
|
+
slate_blue4: 62,
|
|
624
|
+
royal_blue1: 63,
|
|
625
|
+
chartreuse4: 64,
|
|
626
|
+
dark_sea_green4: 65,
|
|
627
|
+
pale_turquoise4: 66,
|
|
628
|
+
steel_blue: 67,
|
|
629
|
+
steel_blue3: 68,
|
|
630
|
+
cornflower_blue: 69,
|
|
631
|
+
chartreuse3: 70,
|
|
632
|
+
dark_sea_green5: 71,
|
|
633
|
+
cadet_blue: 72,
|
|
634
|
+
cadet_blue2: 73,
|
|
635
|
+
sky_blue3: 74,
|
|
636
|
+
steel_blue1: 75,
|
|
637
|
+
chartreuse5: 76,
|
|
638
|
+
pale_green3: 77,
|
|
639
|
+
sea_green3: 78,
|
|
640
|
+
aquamarine3: 79,
|
|
641
|
+
medium_turquoise: 80,
|
|
642
|
+
steel_blue2: 81,
|
|
643
|
+
chartreuse2: 82,
|
|
644
|
+
sea_green2: 83,
|
|
645
|
+
sea_green1: 84,
|
|
646
|
+
sea_green4: 85,
|
|
647
|
+
aquamarine1: 86,
|
|
648
|
+
dark_slate_gray2: 87,
|
|
649
|
+
dark_red2: 88,
|
|
650
|
+
deep_pink5: 89,
|
|
651
|
+
dark_magenta: 90,
|
|
652
|
+
dark_magenta2: 91,
|
|
653
|
+
dark_violet: 92,
|
|
654
|
+
purple2: 93,
|
|
655
|
+
orange5: 94,
|
|
656
|
+
light_pink4: 95,
|
|
657
|
+
plum4: 96,
|
|
658
|
+
medium_purple3: 97,
|
|
659
|
+
medium_purple5: 98,
|
|
660
|
+
slate_blue1: 99,
|
|
661
|
+
yellow4: 100,
|
|
662
|
+
wheat4: 101,
|
|
663
|
+
grey53: 102,
|
|
664
|
+
light_slate_grey: 103,
|
|
665
|
+
medium_purple: 104,
|
|
666
|
+
light_slate_blue: 105,
|
|
667
|
+
yellow5: 106,
|
|
668
|
+
dark_olive_green3: 107,
|
|
669
|
+
dark_sea_green: 108,
|
|
670
|
+
light_sky_blue3: 109,
|
|
671
|
+
light_sky_blue4: 110,
|
|
672
|
+
sky_blue2: 111,
|
|
673
|
+
chartreuse6: 112,
|
|
674
|
+
dark_olive_green4: 113,
|
|
675
|
+
pale_green4: 114,
|
|
676
|
+
dark_sea_green3: 115,
|
|
677
|
+
dark_slate_gray3: 116,
|
|
678
|
+
sky_blue1: 117,
|
|
679
|
+
chartreuse1: 118,
|
|
680
|
+
light_green: 119,
|
|
681
|
+
light_green2: 120,
|
|
682
|
+
pale_green1: 121,
|
|
683
|
+
aquamarine2: 122,
|
|
684
|
+
dark_slate_gray1: 123,
|
|
685
|
+
red3: 124,
|
|
686
|
+
deep_pink6: 125,
|
|
687
|
+
medium_violet_red: 126,
|
|
688
|
+
magenta3: 127,
|
|
689
|
+
dark_violet2: 128,
|
|
690
|
+
purple: 129,
|
|
691
|
+
dark_orange3: 130,
|
|
692
|
+
indian_red: 131,
|
|
693
|
+
hot_pink3: 132,
|
|
694
|
+
medium_orchid3: 133,
|
|
695
|
+
medium_orchid: 134,
|
|
696
|
+
medium_purple2: 135,
|
|
697
|
+
dark_goldenrod: 136,
|
|
698
|
+
light_salmon3: 137,
|
|
699
|
+
rosy_brown: 138,
|
|
700
|
+
grey63: 139,
|
|
701
|
+
medium_purple6: 140,
|
|
702
|
+
medium_purple1: 141,
|
|
703
|
+
gold3: 142,
|
|
704
|
+
dark_khaki: 143,
|
|
705
|
+
navajo_white3: 144,
|
|
706
|
+
grey69: 145,
|
|
707
|
+
light_steel_blue3: 146,
|
|
708
|
+
light_steel_blue: 147,
|
|
709
|
+
yellow3: 148,
|
|
710
|
+
dark_olive_green5: 149,
|
|
711
|
+
dark_sea_green6: 150,
|
|
712
|
+
dark_sea_green2: 151,
|
|
713
|
+
light_cyan3: 152,
|
|
714
|
+
light_sky_blue1: 153,
|
|
715
|
+
green_yellow: 154,
|
|
716
|
+
dark_olive_green2: 155,
|
|
717
|
+
pale_green2: 156,
|
|
718
|
+
dark_sea_green7: 157,
|
|
719
|
+
dark_sea_green1: 158,
|
|
720
|
+
pale_turquoise1: 159,
|
|
721
|
+
red4: 160,
|
|
722
|
+
deep_pink3: 161,
|
|
723
|
+
deep_pink8: 162,
|
|
724
|
+
magenta4: 163,
|
|
725
|
+
magenta5: 164,
|
|
726
|
+
magenta2: 165,
|
|
727
|
+
dark_orange4: 166,
|
|
728
|
+
indian_red2: 167,
|
|
729
|
+
hot_pink4: 168,
|
|
730
|
+
hot_pink2: 169,
|
|
731
|
+
orchid: 170,
|
|
732
|
+
medium_orchid1: 171,
|
|
733
|
+
orange3: 172,
|
|
734
|
+
light_salmon4: 173,
|
|
735
|
+
light_pink3: 174,
|
|
736
|
+
pink3: 175,
|
|
737
|
+
plum3: 176,
|
|
738
|
+
violet: 177,
|
|
739
|
+
gold4: 178,
|
|
740
|
+
light_goldenrod3: 179,
|
|
741
|
+
tan: 180,
|
|
742
|
+
misty_rose3: 181,
|
|
743
|
+
thistle3: 182,
|
|
744
|
+
plum2: 183,
|
|
745
|
+
yellow6: 184,
|
|
746
|
+
khaki3: 185,
|
|
747
|
+
light_goldenrod2: 186,
|
|
748
|
+
light_yellow3: 187,
|
|
749
|
+
grey84: 188,
|
|
750
|
+
light_steel_blue1: 189,
|
|
751
|
+
yellow2: 190,
|
|
752
|
+
dark_olive_green1: 191,
|
|
753
|
+
dark_olive_green6: 192,
|
|
754
|
+
dark_sea_green8: 193,
|
|
755
|
+
honeydew2: 194,
|
|
756
|
+
light_cyan1: 195,
|
|
757
|
+
red1: 196,
|
|
758
|
+
deep_pink2: 197,
|
|
759
|
+
deep_pink1: 198,
|
|
760
|
+
deep_pink9: 199,
|
|
761
|
+
magenta6: 200,
|
|
762
|
+
magenta1: 201,
|
|
763
|
+
orange_red1: 202,
|
|
764
|
+
indian_red1: 203,
|
|
765
|
+
indian_red3: 204,
|
|
766
|
+
hot_pink5: 205,
|
|
767
|
+
hot_pink: 206,
|
|
768
|
+
medium_orchid2: 207,
|
|
769
|
+
dark_orange: 208,
|
|
770
|
+
salmon1: 209,
|
|
771
|
+
light_coral: 210,
|
|
772
|
+
pale_violet_red1: 211,
|
|
773
|
+
orchid2: 212,
|
|
774
|
+
orchid1: 213,
|
|
775
|
+
orange1: 214,
|
|
776
|
+
sandy_brown: 215,
|
|
777
|
+
light_salmon1: 216,
|
|
778
|
+
light_pink1: 217,
|
|
779
|
+
pink1: 218,
|
|
780
|
+
plum1: 219,
|
|
781
|
+
gold1: 220,
|
|
782
|
+
light_goldenrod4: 221,
|
|
783
|
+
light_goldenrod5: 222,
|
|
784
|
+
navajo_white1: 223,
|
|
785
|
+
misty_rose1: 224,
|
|
786
|
+
thistle1: 225,
|
|
787
|
+
yellow1: 226,
|
|
788
|
+
light_goldenrod1: 227,
|
|
789
|
+
khaki1: 228,
|
|
790
|
+
wheat1: 229,
|
|
791
|
+
cornsilk1: 230,
|
|
792
|
+
grey100: 231,
|
|
793
|
+
// Grayscale ramp (232-255)
|
|
794
|
+
grey3: 232,
|
|
795
|
+
grey7: 233,
|
|
796
|
+
grey11: 234,
|
|
797
|
+
grey15: 235,
|
|
798
|
+
grey19: 236,
|
|
799
|
+
grey23: 237,
|
|
800
|
+
grey27: 238,
|
|
801
|
+
grey30: 239,
|
|
802
|
+
grey35: 240,
|
|
803
|
+
grey39: 241,
|
|
804
|
+
grey42: 242,
|
|
805
|
+
grey46: 243,
|
|
806
|
+
grey50: 244,
|
|
807
|
+
grey54: 245,
|
|
808
|
+
grey58: 246,
|
|
809
|
+
grey62: 247,
|
|
810
|
+
grey66: 248,
|
|
811
|
+
grey70: 249,
|
|
812
|
+
grey74: 250,
|
|
813
|
+
grey78: 251,
|
|
814
|
+
grey82: 252,
|
|
815
|
+
grey85: 253,
|
|
816
|
+
grey89: 254,
|
|
817
|
+
grey93: 255,
|
|
818
|
+
};
|
|
819
|
+
// Add gray→grey aliases
|
|
820
|
+
for (const [name, index] of Object.entries(ANSI_COLOR_NAMES)) {
|
|
821
|
+
if (name.includes("grey")) {
|
|
822
|
+
ANSI_COLOR_NAMES[name.replace("grey", "gray")] = index;
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
//# sourceMappingURL=color.js.map
|