@promptctl/rich-js 0.28.0 → 0.29.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 +7 -7
- package/dist/core/animation.d.ts +37 -37
- package/dist/core/animation.js +61 -61
- package/dist/core/ansi.d.ts +4 -4
- package/dist/core/ansi.js +9 -9
- package/dist/core/bidi.js +6 -6
- package/dist/core/cells.d.ts +1 -1
- package/dist/core/cells.js +5 -5
- package/dist/core/clock.d.ts +1 -1
- package/dist/core/color.d.ts +50 -50
- package/dist/core/color.js +69 -69
- package/dist/core/console.d.ts +8 -8
- package/dist/core/console.js +5 -5
- package/dist/core/control-codes.d.ts +3 -3
- package/dist/core/control-codes.js +7 -7
- package/dist/core/easing.d.ts +40 -40
- package/dist/core/easing.js +40 -40
- package/dist/core/env.d.ts +1 -1
- package/dist/core/env.js +1 -1
- package/dist/core/export-html.js +1 -1
- package/dist/core/export-lines.d.ts +11 -11
- package/dist/core/export-lines.js +12 -12
- package/dist/core/export-svg.d.ts +3 -3
- package/dist/core/export-svg.js +4 -4
- package/dist/core/markup.js +1 -1
- package/dist/core/memo.d.ts +1 -1
- package/dist/core/memo.js +1 -1
- package/dist/core/oklch.d.ts +14 -14
- package/dist/core/oklch.js +10 -10
- package/dist/core/orient.d.ts +3 -3
- package/dist/core/orient.js +3 -3
- package/dist/core/paint.d.ts +9 -9
- package/dist/core/paint.js +3 -3
- package/dist/core/pretty.d.ts +1 -1
- package/dist/core/pretty.js +3 -3
- package/dist/core/protocol.d.ts +26 -26
- package/dist/core/protocol.js +22 -22
- package/dist/core/render.d.ts +11 -11
- package/dist/core/render.js +12 -12
- package/dist/core/segment.d.ts +3 -3
- package/dist/core/segment.js +5 -5
- package/dist/core/strip.d.ts +83 -83
- package/dist/core/strip.js +70 -70
- package/dist/core/style.d.ts +20 -20
- package/dist/core/style.js +55 -55
- package/dist/core/text.d.ts +2 -2
- package/dist/core/text.js +5 -5
- package/dist/core/timeline.d.ts +5 -5
- package/dist/core/timeline.js +9 -9
- package/dist/core/tween.d.ts +6 -6
- package/dist/core/tween.js +10 -10
- package/dist/core/view.d.ts +4 -4
- package/dist/core/view.js +12 -12
- package/dist/host/app.d.ts +9 -9
- package/dist/host/app.js +12 -12
- package/dist/host/host-environment.d.ts +2 -2
- package/dist/host/host-environment.js +2 -2
- package/dist/host/index.d.ts +2 -2
- package/dist/host/input.d.ts +7 -7
- package/dist/host/input.js +4 -4
- package/dist/host/terminal-colors.d.ts +2 -2
- package/dist/host/terminal-colors.js +4 -4
- package/dist/host/terminal-host.d.ts +2 -2
- package/dist/host/terminal-host.js +1 -1
- package/dist/index.d.ts +14 -14
- package/dist/index.js +10 -10
- package/dist/node/prompt.d.ts +1 -1
- package/dist/node/prompt.js +1 -1
- package/dist/node/terminal-host.d.ts +1 -1
- package/dist/node/traceback.js +2 -2
- package/dist/renderables/change.js +2 -2
- package/dist/renderables/effect.d.ts +39 -39
- package/dist/renderables/effect.js +45 -45
- package/dist/renderables/effects.d.ts +81 -81
- package/dist/renderables/effects.js +157 -157
- package/dist/renderables/embed.d.ts +1 -1
- package/dist/renderables/embed.js +2 -2
- package/dist/renderables/flexStrip.d.ts +7 -7
- package/dist/renderables/flexStrip.js +15 -15
- package/dist/renderables/frames.d.ts +6 -6
- package/dist/renderables/frames.js +11 -11
- package/dist/renderables/glyph-effect.d.ts +15 -15
- package/dist/renderables/glyph-effect.js +17 -17
- package/dist/renderables/glyph-effects.d.ts +7 -7
- package/dist/renderables/glyph-effects.js +16 -16
- package/dist/renderables/html-entities.d.ts +1 -1
- package/dist/renderables/html-entities.js +1 -1
- package/dist/renderables/lifecycle.d.ts +4 -4
- package/dist/renderables/lifecycle.js +12 -12
- package/dist/renderables/live.d.ts +2 -2
- package/dist/renderables/live.js +7 -7
- package/dist/renderables/markdown-parse.js +3 -3
- package/dist/renderables/panel.js +3 -3
- package/dist/renderables/progress.d.ts +1 -1
- package/dist/renderables/progress.js +1 -1
- package/dist/renderables/progressBar.d.ts +1 -1
- package/dist/renderables/progressBar.js +6 -6
- package/dist/renderables/prompt.d.ts +1 -1
- package/dist/renderables/scroll.d.ts +1 -1
- package/dist/renderables/scroll.js +3 -3
- package/dist/renderables/spinner.d.ts +4 -4
- package/dist/renderables/spinner.js +10 -10
- package/dist/renderables/syntax.d.ts +2 -2
- package/dist/renderables/syntax.js +2 -2
- package/dist/renderables/table.js +3 -3
- package/dist/renderables/traceback.d.ts +1 -1
- package/dist/renderables/traceback.js +1 -1
- package/dist/renderables/tree.js +3 -3
- package/dist/template-bindings/animation-funcs.d.ts +14 -14
- package/dist/template-bindings/animation-funcs.js +27 -27
- package/dist/template-bindings/color-funcs.d.ts +14 -14
- package/dist/template-bindings/color-funcs.js +25 -25
- package/dist/template-bindings/index.d.ts +9 -9
- package/dist/template-bindings/index.js +9 -9
- package/dist/template-bindings/palette-funcs.d.ts +1 -1
- package/dist/template-bindings/palette-funcs.js +3 -3
- package/dist/template-bindings/style-funcs.d.ts +5 -5
- package/dist/template-bindings/style-funcs.js +16 -16
- package/dist/themes/{transpose.d.ts → adjust.d.ts} +23 -23
- package/dist/themes/{transpose.js → adjust.js} +28 -28
- package/dist/themes/buildPalette.d.ts +3 -3
- package/dist/themes/buildPalette.js +20 -20
- package/dist/themes/colorMath.d.ts +16 -16
- package/dist/themes/colorMath.js +32 -32
- package/dist/themes/data/ansi-tables.d.ts +2 -2
- package/dist/themes/data/ansi-tables.js +2 -2
- package/dist/themes/data/types.d.ts +4 -4
- package/dist/themes/data/types.js +2 -2
- package/dist/themes/palette.d.ts +12 -12
- package/dist/themes/palette.js +16 -16
- package/dist/themes/ramp.d.ts +17 -17
- package/dist/themes/ramp.js +12 -12
- package/dist/themes/registry.js +4 -4
- package/dist/themes/terminalThemes.d.ts +1 -1
- package/dist/themes/terminalThemes.js +1 -1
- package/dist/widgets/button.d.ts +2 -2
- package/dist/widgets/button.js +4 -4
- package/dist/widgets/checkbox.d.ts +2 -2
- package/dist/widgets/checkbox.js +2 -2
- package/dist/widgets/dropdown.d.ts +2 -2
- package/dist/widgets/dropdown.js +3 -3
- package/dist/widgets/event-router.d.ts +6 -6
- package/dist/widgets/event-router.js +2 -2
- package/dist/widgets/focus-manager.d.ts +3 -3
- package/dist/widgets/focus-manager.js +3 -3
- package/dist/widgets/index.d.ts +2 -2
- package/dist/widgets/index.js +1 -1
- package/dist/widgets/ink.d.ts +3 -3
- package/dist/widgets/ink.js +4 -4
- package/dist/widgets/slider.d.ts +2 -2
- package/dist/widgets/static-item.d.ts +2 -2
- package/dist/widgets/text-input.d.ts +2 -2
- package/dist/widgets/text-input.js +5 -5
- package/dist/widgets/themed-widget.js +1 -1
- package/dist/widgets/toggle.d.ts +3 -3
- package/dist/widgets/toggle.js +3 -3
- package/dist/widgets/types.d.ts +6 -6
- package/dist/widgets/types.js +2 -2
- package/dist/widgets/widget-app.d.ts +10 -10
- package/dist/widgets/widget-app.js +8 -8
- package/dist/widgets/widget-base.d.ts +2 -2
- package/package.json +1 -1
package/dist/core/color.js
CHANGED
|
@@ -9,7 +9,7 @@ import { detectTextOrder } from "./text-order.js";
|
|
|
9
9
|
function hex2(byte) {
|
|
10
10
|
return byte.toString(16).padStart(2, "0");
|
|
11
11
|
}
|
|
12
|
-
// [LAW:one-source-of-truth] The one statement of a
|
|
12
|
+
// [LAW:one-source-of-truth] The one statement of a color byte's range: the
|
|
13
13
|
// constructor asserts it and the string parser reports it, from this predicate.
|
|
14
14
|
function isByte(v) {
|
|
15
15
|
return Number.isInteger(v) && v >= 0 && v <= 255;
|
|
@@ -75,12 +75,12 @@ export class ColorRgba {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
/**
|
|
78
|
-
* The surface a terminal draws a translucent
|
|
78
|
+
* The surface a terminal draws a translucent color over. A terminal cannot
|
|
79
79
|
* know what lies under its cells, so the SGR writer (`Style.toSgrCodes`), the
|
|
80
80
|
* exports that picture its output (`resolveLook`), the strip's seam test and
|
|
81
81
|
* the contrast choosers (`themes/colorMath`) all composite over this one
|
|
82
|
-
*
|
|
83
|
-
* the
|
|
82
|
+
* color. [LAW:one-source-of-truth] One constant, so
|
|
83
|
+
* the color text is chosen against is the color the writer draws.
|
|
84
84
|
*/
|
|
85
85
|
export const SURFACE_BLACK = new ColorRgba(0, 0, 0);
|
|
86
86
|
/**
|
|
@@ -117,7 +117,7 @@ function luminanceRatio(la, lb) {
|
|
|
117
117
|
// --- ColorTable ---
|
|
118
118
|
// [LAW:one-source-of-truth] The one distance every table scan ranks by, so
|
|
119
119
|
// `matchWhere`'s "nearest by the distance `match` uses" cannot drift, and
|
|
120
|
-
// `Effected` weighs a written
|
|
120
|
+
// `Effected` weighs a written color against `ColorSpec.matchOn` by it too.
|
|
121
121
|
export function rgbDistance(a, b) {
|
|
122
122
|
const dr = a.red - b.red;
|
|
123
123
|
const dg = a.green - b.green;
|
|
@@ -127,7 +127,7 @@ export function rgbDistance(a, b) {
|
|
|
127
127
|
/**
|
|
128
128
|
* An indexed palette: entry `i` of `colors` is terminal index `firstIndex + i`.
|
|
129
129
|
* `firstIndex` lets a table hold only the part of a palette a downgrade may
|
|
130
|
-
* choose (the 256-
|
|
130
|
+
* choose (the 256-color cube and grey ramp start at 16) while every index it
|
|
131
131
|
* reports is the terminal's own.
|
|
132
132
|
*/
|
|
133
133
|
export class ColorTable {
|
|
@@ -135,7 +135,7 @@ export class ColorTable {
|
|
|
135
135
|
/** Each entry's relative luminance. */
|
|
136
136
|
luminances;
|
|
137
137
|
firstIndex;
|
|
138
|
-
// Keyed by
|
|
138
|
+
// Keyed by colors a host computes without end (ramp stops, mixes), so bounded.
|
|
139
139
|
matchMemo = new Memo();
|
|
140
140
|
readableMemo = new Memo();
|
|
141
141
|
constructor(colors, firstIndex = 0) {
|
|
@@ -209,7 +209,7 @@ export class ColorTable {
|
|
|
209
209
|
}
|
|
210
210
|
/**
|
|
211
211
|
* The nearest entry to `value` (the distance `match` uses) among those
|
|
212
|
-
* `accept` takes, given each entry's
|
|
212
|
+
* `accept` takes, given each entry's color and terminal index; `undefined`
|
|
213
213
|
* when it takes none. Entries are offered nearest-first (ties to the lower
|
|
214
214
|
* index) and the first taken wins, so an expensive predicate runs only as
|
|
215
215
|
* far out as the answer. Uncached: the predicate is the caller's, and a
|
|
@@ -232,7 +232,7 @@ export var ColorDepth;
|
|
|
232
232
|
ColorDepth[ColorDepth["WINDOWS"] = 4] = "WINDOWS";
|
|
233
233
|
})(ColorDepth || (ColorDepth = {}));
|
|
234
234
|
/**
|
|
235
|
-
* How many
|
|
235
|
+
* How many colors a depth can name, as a rank. WINDOWS is a sixteen-color
|
|
236
236
|
* depth whose enum value sits above TRUECOLOR, so the enum's order is not this.
|
|
237
237
|
* STANDARD and WINDOWS share a rank: the same sixteen slots, drawn by
|
|
238
238
|
* different terminals, so each converts to the other by keeping the slot.
|
|
@@ -250,7 +250,7 @@ function fidelity(depth) {
|
|
|
250
250
|
return 3;
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
|
-
// The depths a
|
|
253
|
+
// The depths a color system is named for. Its keys and "auto" are the whole
|
|
254
254
|
// vocabulary: `ColorSystemName` is derived from them, so the type and the
|
|
255
255
|
// table cannot disagree. [LAW:one-source-of-truth]
|
|
256
256
|
const COLOR_SYSTEM_DEPTHS = {
|
|
@@ -259,11 +259,11 @@ const COLOR_SYSTEM_DEPTHS = {
|
|
|
259
259
|
ansi: ColorDepth.STANDARD,
|
|
260
260
|
none: null,
|
|
261
261
|
};
|
|
262
|
-
// [LAW:one-source-of-truth] What the environment says about
|
|
262
|
+
// [LAW:one-source-of-truth] What the environment says about color, by the
|
|
263
263
|
// value it says it with: FORCE_COLOR values (the chalk/supports-color
|
|
264
|
-
// convention), TERM_PROGRAM identifiers, and exact TERM names whose
|
|
264
|
+
// convention), TERM_PROGRAM identifiers, and exact TERM names whose color
|
|
265
265
|
// capability is known. A different vocabulary from `ColorSystemName`, so a
|
|
266
|
-
// different table: `FORCE_COLOR=none` is not a request for no
|
|
266
|
+
// different table: `FORCE_COLOR=none` is not a request for no color. A `Map`,
|
|
267
267
|
// so a value naming an `Object.prototype` member is unknown, not a function.
|
|
268
268
|
// `null` means "no color".
|
|
269
269
|
const ENV_DEPTHS = new Map([
|
|
@@ -299,7 +299,7 @@ const ENV_DEPTHS = new Map([
|
|
|
299
299
|
* in the env values, not in which checks execute.
|
|
300
300
|
*/
|
|
301
301
|
export function detectColorSystem(options = {}) {
|
|
302
|
-
// NO_COLOR and FORCE_COLOR are preferences about
|
|
302
|
+
// NO_COLOR and FORCE_COLOR are preferences about color, not facts about the
|
|
303
303
|
// terminal, so they sit outside the probe. NO_COLOR (any non-empty value)
|
|
304
304
|
// beats FORCE_COLOR; FORCE_COLOR beats TTY/TERM detection.
|
|
305
305
|
const noColor = envOf(options)["NO_COLOR"];
|
|
@@ -359,18 +359,18 @@ function terminalColorSystem(options) {
|
|
|
359
359
|
return ColorDepth.STANDARD;
|
|
360
360
|
}
|
|
361
361
|
/**
|
|
362
|
-
* Resolve a
|
|
362
|
+
* Resolve a color spec into an `OutputTarget`.
|
|
363
363
|
*
|
|
364
364
|
* [LAW:single-enforcer] The one place a spec becomes both facts. A hyperlink is
|
|
365
|
-
* not a
|
|
366
|
-
*
|
|
365
|
+
* not a color: an explicit depth — `"none"` and `null` included — states a
|
|
366
|
+
* color choice and keeps links, and under `"auto"` links follow what the
|
|
367
367
|
* terminal can take (no TTY, TERM=dumb: none) while NO_COLOR and FORCE_COLOR=0,
|
|
368
|
-
*
|
|
368
|
+
* color preferences, leave them alone. A FORCE_COLOR that forces color on
|
|
369
369
|
* declares the destination takes escapes, so it keeps links on a pipe too.
|
|
370
370
|
*/
|
|
371
|
-
export function
|
|
371
|
+
export function resolveOutputTarget(spec, options = {}) {
|
|
372
372
|
const reducedMotion = options.reducedMotion ?? false;
|
|
373
|
-
// Ahead of both arms: a
|
|
373
|
+
// Ahead of both arms: a color spec says nothing about order.
|
|
374
374
|
const textOrder = options.textOrder ?? detectTextOrder(envOf(options), isTTYOf(options));
|
|
375
375
|
if (spec !== "auto") {
|
|
376
376
|
return {
|
|
@@ -389,7 +389,7 @@ export function resolveDestination(spec, options = {}) {
|
|
|
389
389
|
};
|
|
390
390
|
}
|
|
391
391
|
/**
|
|
392
|
-
* Resolve a
|
|
392
|
+
* Resolve a color system name into a `ColorDepth` (or `null` for no color).
|
|
393
393
|
*
|
|
394
394
|
* `"auto"` triggers env-based detection; every other name is a fixed depth.
|
|
395
395
|
* A name outside the vocabulary — reachable only from untyped JavaScript —
|
|
@@ -429,12 +429,12 @@ export class ColorSpec {
|
|
|
429
429
|
return this.type === ColorDepth.DEFAULT;
|
|
430
430
|
}
|
|
431
431
|
/**
|
|
432
|
-
* The
|
|
432
|
+
* The color every terminal draws this spec as, where that is fixed — before
|
|
433
433
|
* any alpha is flattened, so a translucent value is drawn composited over
|
|
434
434
|
* its ground (`flattenAlpha`) and should be measured that way: a
|
|
435
|
-
* truecolor value, or a 256-
|
|
435
|
+
* truecolor value, or a 256-color cube or grey-ramp entry (xterm fixes
|
|
436
436
|
* indices 16–255, and `fromAnsi` types only those as EIGHT_BIT). ANSI 0–15,
|
|
437
|
-
* the default
|
|
437
|
+
* the default color and a blend reaching either are the terminal theme's
|
|
438
438
|
* own, so they have none.
|
|
439
439
|
*/
|
|
440
440
|
get fixedValue() {
|
|
@@ -553,20 +553,20 @@ export class ColorSpec {
|
|
|
553
553
|
return ColorSpec.fromRgba(new ColorRgba(r, g, b));
|
|
554
554
|
}
|
|
555
555
|
/**
|
|
556
|
-
* The
|
|
557
|
-
* parses to. Two fixed
|
|
558
|
-
* theme's own
|
|
556
|
+
* The color `t` of the way from `from` to `to`: what `blend(from,to,t)`
|
|
557
|
+
* parses to. Two fixed colors mix to a fixed color. A mix reaching a
|
|
558
|
+
* theme's own color stays a mix until it is drawn, so whatever theme draws
|
|
559
559
|
* an end draws the mix from it: exported under a theme whose `blue` is
|
|
560
560
|
* #61afef, a mix with `blue` starts from #61afef. A terminal is told its RGB
|
|
561
561
|
* under the standard table, the only one a render has.
|
|
562
562
|
*
|
|
563
|
-
* Each end is one opaque
|
|
563
|
+
* Each end is one opaque color: `default` is no color to mix, and a
|
|
564
564
|
* translucent end has no one shade until it is laid on a ground.
|
|
565
565
|
*/
|
|
566
566
|
static blend(from, to, t) {
|
|
567
567
|
for (const end of [from, to]) {
|
|
568
568
|
if (end.isDefault)
|
|
569
|
-
throw new ColorParseError(`A blend cannot mix "default", which is no
|
|
569
|
+
throw new ColorParseError(`A blend cannot mix "default", which is no color`);
|
|
570
570
|
if (end.value !== undefined && end.value.alpha < 1) {
|
|
571
571
|
throw new ColorParseError(`A blend's ends are opaque; "${end.name}" is translucent`);
|
|
572
572
|
}
|
|
@@ -589,21 +589,21 @@ export class ColorSpec {
|
|
|
589
589
|
}
|
|
590
590
|
/**
|
|
591
591
|
* The spec that draws `value` nearest to it at `depth` on a terminal known
|
|
592
|
-
* to show `theme`, as the
|
|
592
|
+
* to show `theme`, as the color of the glyph (`foreground`) or of the
|
|
593
593
|
* ground. Where `downgrade` knows no terminal, and so rounds only against
|
|
594
|
-
*
|
|
595
|
-
* sixteen), this rounds against every
|
|
596
|
-
* look `theme` fixes: the default
|
|
597
|
-
*
|
|
598
|
-
* moved a little is drawn as the
|
|
599
|
-
* gives two slots one
|
|
594
|
+
* colors every terminal fixes (or, at sixteen colors, the stock
|
|
595
|
+
* sixteen), this rounds against every color the depth can write whose
|
|
596
|
+
* look `theme` fixes: the default color, the theme's sixteen, and at 256
|
|
597
|
+
* colors the cube and grey ramp too. A color read off any of those and
|
|
598
|
+
* moved a little is drawn as the color it came from — or, where the theme
|
|
599
|
+
* gives two slots one color, as the lower slot, which looks the same.
|
|
600
600
|
*
|
|
601
|
-
* `value` is opaque: a translucent
|
|
601
|
+
* `value` is opaque: a translucent color has no one look until it is laid
|
|
602
602
|
* on a ground (`flattenAlpha`).
|
|
603
603
|
*/
|
|
604
604
|
static matchOn(value, depth, theme, foreground) {
|
|
605
605
|
if (value.alpha < 1)
|
|
606
|
-
throw new RangeError(`matchOn rounds an opaque
|
|
606
|
+
throw new RangeError(`matchOn rounds an opaque color; got alpha ${value.alpha}`);
|
|
607
607
|
if (depth === ColorDepth.TRUECOLOR)
|
|
608
608
|
return ColorSpec.fromRgba(value);
|
|
609
609
|
if (depth === ColorDepth.DEFAULT)
|
|
@@ -621,23 +621,23 @@ export class ColorSpec {
|
|
|
621
621
|
return candidates.reduce((best, next) => (rgbDistance(next[1], value) < rgbDistance(best[1], value) ? next : best))[0];
|
|
622
622
|
}
|
|
623
623
|
/**
|
|
624
|
-
* Every
|
|
624
|
+
* Every color `depth` writes by index, each with the color a terminal
|
|
625
625
|
* known to show `theme` draws it in, lowest index first: the theme's
|
|
626
|
-
* sixteen, and at 256
|
|
627
|
-
* drawn alike as glyph and as ground, which the default
|
|
628
|
-
* it is not among them. Truecolor writes a
|
|
629
|
-
* depth only the default, so neither writes any by index. The
|
|
626
|
+
* sixteen, and at 256 colors the cube and grey ramp after them. Each is
|
|
627
|
+
* drawn alike as glyph and as ground, which the default color is not, so
|
|
628
|
+
* it is not among them. Truecolor writes a color itself and the default
|
|
629
|
+
* depth only the default, so neither writes any by index. The colors
|
|
630
630
|
* `matchOn` rounds to, but for the default, read off the same two tables.
|
|
631
631
|
*/
|
|
632
632
|
static indexed(depth, theme) {
|
|
633
633
|
return indexedMemo.get(theme, () => new Memo()).get(`${depth}`, () => listIndexed(depth, theme));
|
|
634
634
|
}
|
|
635
635
|
/**
|
|
636
|
-
* The spec a slot is written in once its
|
|
636
|
+
* The spec a slot is written in once its color moves from `was`, what its
|
|
637
637
|
* written spec draws on `theme`, to the opaque `now`: `matchOn`'s — or
|
|
638
638
|
* none, where the written spec is as near `now` as that match. A move the
|
|
639
|
-
* depth cannot show is no move, so below truecolor a
|
|
640
|
-
* off any
|
|
639
|
+
* depth cannot show is no move, so below truecolor a color moved a little
|
|
640
|
+
* off any color the depth can write — a theme slot, the default color,
|
|
641
641
|
* the cube — keeps the spec it was written in.
|
|
642
642
|
*/
|
|
643
643
|
static matchMove(was, now, depth, theme, foreground) {
|
|
@@ -653,7 +653,7 @@ export class ColorSpec {
|
|
|
653
653
|
}
|
|
654
654
|
// --- private ---
|
|
655
655
|
performDowngrade(targetSystem) {
|
|
656
|
-
// The
|
|
656
|
+
// The color as the terminal this depth assumes draws it: a blend's named
|
|
657
657
|
// ends are the Windows console's own at WINDOWS.
|
|
658
658
|
const triplet = this.getTruecolor(resolveTerminal(undefined, targetSystem));
|
|
659
659
|
switch (targetSystem) {
|
|
@@ -662,7 +662,7 @@ export class ColorSpec {
|
|
|
662
662
|
case ColorDepth.STANDARD:
|
|
663
663
|
case ColorDepth.WINDOWS: {
|
|
664
664
|
// An ANSI slot is already one of the sixteen either depth writes; only
|
|
665
|
-
// a fixed
|
|
665
|
+
// a fixed color is matched against the depth's table, as Rich does.
|
|
666
666
|
const index = this.number !== undefined && this.number < 16 ? this.number : downgradeTable(targetSystem).match(triplet);
|
|
667
667
|
return new ColorSpec(`color(${index})`, targetSystem, index);
|
|
668
668
|
}
|
|
@@ -673,7 +673,7 @@ export class ColorSpec {
|
|
|
673
673
|
}
|
|
674
674
|
}
|
|
675
675
|
}
|
|
676
|
-
/** The cube or grey-ramp entry nearest `value`, and its
|
|
676
|
+
/** The cube or grey-ramp entry nearest `value`, and its color. */
|
|
677
677
|
function cubeCandidate(value) {
|
|
678
678
|
const index = EIGHT_BIT_DOWNGRADE_TABLE.match(value);
|
|
679
679
|
return [ColorSpec.fromAnsi(index), EIGHT_BIT_DOWNGRADE_TABLE.get(index)];
|
|
@@ -699,7 +699,7 @@ function mix(from, to, t, theme) {
|
|
|
699
699
|
return blendRgb(from.getTruecolor(theme), to.getTruecolor(theme), t);
|
|
700
700
|
}
|
|
701
701
|
// How a blend spells an end: by what it draws as, so every spelling of one
|
|
702
|
-
//
|
|
702
|
+
// color ("blue", "color(4)", an EIGHT_BIT 4) gives the blend one name.
|
|
703
703
|
function blendTerm(end) {
|
|
704
704
|
return end.fixedValue?.hex ?? (end.number !== undefined ? `color(${end.number})` : end.name);
|
|
705
705
|
}
|
|
@@ -802,8 +802,8 @@ function parseByte(key, digits, field) {
|
|
|
802
802
|
return n;
|
|
803
803
|
}
|
|
804
804
|
// --- Utility functions ---
|
|
805
|
-
// [LAW:single-enforcer] The hex
|
|
806
|
-
// every string spelling a
|
|
805
|
+
// [LAW:single-enforcer] The hex color grammar, checked here and nowhere else:
|
|
806
|
+
// every string spelling a color in hex — a ColorSpec, a theme's data, a color
|
|
807
807
|
// reference, a template argument — becomes one through the three parsers below,
|
|
808
808
|
// and each is this check at the lengths it admits. Each digit pair is a byte, so
|
|
809
809
|
// the grammar holding is what keeps `ColorRgba`'s channels in range.
|
|
@@ -814,12 +814,12 @@ const HEX_GRAMMARS = { 6: "RRGGBB", 8: "RRGGBBAA" };
|
|
|
814
814
|
function hexColor(input, lead, digits, lengths) {
|
|
815
815
|
if (!lengths.includes(digits.length) || !HEX_DIGITS_RE.test(digits)) {
|
|
816
816
|
const expected = lengths.map((n) => lead + HEX_GRAMMARS[n]).join(" or ");
|
|
817
|
-
throw new ColorParseError(`Invalid hex
|
|
817
|
+
throw new ColorParseError(`Invalid hex color ${JSON.stringify(input)} (expected ${expected})`);
|
|
818
818
|
}
|
|
819
819
|
const byte = (at) => parseInt(digits.slice(at, at + 2), 16);
|
|
820
820
|
return new ColorRgba(byte(0), byte(2), byte(4), digits.length === 8 ? byte(6) / 255 : 1);
|
|
821
821
|
}
|
|
822
|
-
/** Six hex digits, no `#`, as an opaque
|
|
822
|
+
/** Six hex digits, no `#`, as an opaque color. @throws {ColorParseError} on anything else. */
|
|
823
823
|
export function parseRgbHex(hex) {
|
|
824
824
|
return hexColor(hex, "", hex, [6]);
|
|
825
825
|
}
|
|
@@ -839,7 +839,7 @@ export function blendRgb(color1, color2, crossFade = 0.5) {
|
|
|
839
839
|
}
|
|
840
840
|
// --- TerminalTheme ---
|
|
841
841
|
/**
|
|
842
|
-
* What a terminal draws with: the part of a `TerminalTheme` a
|
|
842
|
+
* What a terminal draws with: the part of a `TerminalTheme` a color resolves
|
|
843
843
|
* against.
|
|
844
844
|
*/
|
|
845
845
|
export class TerminalColors {
|
|
@@ -853,17 +853,17 @@ export class TerminalColors {
|
|
|
853
853
|
// [LAW:parse-dont-validate] Every reader indexes `ansiColors` 0–15 as the
|
|
854
854
|
// terminal's sixteen, so a theme is the proof it holds exactly those.
|
|
855
855
|
if (ansiColors.firstIndex !== 0 || ansiColors.size !== 16) {
|
|
856
|
-
throw new RangeError(`a TerminalTheme's ansiColors are the sixteen ANSI
|
|
856
|
+
throw new RangeError(`a TerminalTheme's ansiColors are the sixteen ANSI colors, indices 0–15; got ${ansiColors.size} from index ${ansiColors.firstIndex}`);
|
|
857
857
|
}
|
|
858
858
|
}
|
|
859
859
|
}
|
|
860
860
|
/**
|
|
861
|
-
* A terminal theme — surface/foreground baseline, the sixteen ANSI
|
|
861
|
+
* A terminal theme — surface/foreground baseline, the sixteen ANSI colors,
|
|
862
862
|
* and a semantic palette.
|
|
863
863
|
*
|
|
864
|
-
* **`ansiColors` is the theme's own sixteen
|
|
864
|
+
* **`ansiColors` is the theme's own sixteen colors**, the shades a terminal
|
|
865
865
|
* showing this theme draws `red`, `blue` and the rest in. `ColorSpec.parse("red")`
|
|
866
|
-
* is ANSI
|
|
866
|
+
* is ANSI color 1 under every theme; which red that is, is the theme's to say,
|
|
867
867
|
* as it is in Rich, where each `TerminalTheme` carries its own table.
|
|
868
868
|
*/
|
|
869
869
|
export class TerminalTheme extends TerminalColors {
|
|
@@ -914,8 +914,8 @@ function build256Table() {
|
|
|
914
914
|
}
|
|
915
915
|
/**
|
|
916
916
|
* The Windows console's own sixteen (its default Campbell scheme), in ANSI
|
|
917
|
-
* index order: a WINDOWS
|
|
918
|
-
* STANDARD one is, so slot `n` here is the
|
|
917
|
+
* index order: a WINDOWS color is written as the same `30+n`/`90+n` SGR a
|
|
918
|
+
* STANDARD one is, so slot `n` here is the color the console draws for it.
|
|
919
919
|
*/
|
|
920
920
|
function buildWindowsTable() {
|
|
921
921
|
return [
|
|
@@ -940,8 +940,8 @@ function buildWindowsTable() {
|
|
|
940
940
|
export const STANDARD_TABLE = new ColorTable(buildStandard16());
|
|
941
941
|
export const EIGHT_BIT_TABLE = new ColorTable(build256Table());
|
|
942
942
|
/**
|
|
943
|
-
* What a downgrade to 256
|
|
944
|
-
* indices 16–255. Indices 0–15 are the terminal's own ANSI
|
|
943
|
+
* What a downgrade to 256 colors may choose: the cube and the grey ramp,
|
|
944
|
+
* indices 16–255. Indices 0–15 are the terminal's own ANSI colors, which
|
|
945
945
|
* every theme redefines, so their RGB is unknown and a match against them is
|
|
946
946
|
* a guess; Python Rich never picks them either.
|
|
947
947
|
*/
|
|
@@ -955,13 +955,13 @@ export const WINDOWS_TABLE = new ColorTable(buildWindowsTable());
|
|
|
955
955
|
// `themes/* -> core/color`, with no runtime back-edge.
|
|
956
956
|
//
|
|
957
957
|
// `getTruecolor()` retains a fallback for callers that omit `theme`: the
|
|
958
|
-
// terminal a
|
|
958
|
+
// terminal a color's depth assumes, its own sixteen and no palette, which the
|
|
959
959
|
// lookups it serves never read.
|
|
960
960
|
const INTERNAL_DEFAULT_TERMINAL = new TerminalColors(new ColorRgba(0, 0, 0), new ColorRgba(255, 255, 255), STANDARD_TABLE);
|
|
961
|
-
/** The Windows console in its default Campbell scheme: a WINDOWS
|
|
961
|
+
/** The Windows console in its default Campbell scheme: a WINDOWS color's terminal. */
|
|
962
962
|
const WINDOWS_CONSOLE_TERMINAL = new TerminalColors(WINDOWS_TABLE.get(0), WINDOWS_TABLE.get(7), WINDOWS_TABLE);
|
|
963
963
|
/**
|
|
964
|
-
* The terminal a
|
|
964
|
+
* The terminal a color at `depth` is drawn by: `theme`, or when a caller names
|
|
965
965
|
* none, the one the depth assumes — the Windows console at WINDOWS, the VGA
|
|
966
966
|
* sixteen otherwise — for `ColorSpec.getTruecolor` and the contrast measurement
|
|
967
967
|
* that reads it. (Widgets fall back to `DEFAULT_TERMINAL_THEME`, which carries a
|
|
@@ -971,9 +971,9 @@ export function resolveTerminal(theme, depth) {
|
|
|
971
971
|
return theme ?? (depth === ColorDepth.WINDOWS ? WINDOWS_CONSOLE_TERMINAL : INTERNAL_DEFAULT_TERMINAL);
|
|
972
972
|
}
|
|
973
973
|
/**
|
|
974
|
-
* The table a downgrade to `depth` rounds a fixed
|
|
975
|
-
* [LAW:one-source-of-truth] `ColorSpec.downgrade` picks the index a
|
|
976
|
-
* written as from it, and colorMath hands back its entries as
|
|
974
|
+
* The table a downgrade to `depth` rounds a fixed color against.
|
|
975
|
+
* [LAW:one-source-of-truth] `ColorSpec.downgrade` picks the index a color is
|
|
976
|
+
* written as from it, and colorMath hands back its entries as colors the
|
|
977
977
|
* writer rounds to those same indices.
|
|
978
978
|
*/
|
|
979
979
|
export function downgradeTable(depth) {
|
package/dist/core/console.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Style, Theme } from "./style.js";
|
|
5
5
|
import { ColorDepth } from "./color.js";
|
|
6
6
|
import type { TextOrder } from "./text-order.js";
|
|
7
|
-
import type { ColorSystemName,
|
|
7
|
+
import type { ColorSystemName, OutputTarget } from "./color.js";
|
|
8
8
|
import type { Env } from "./env.js";
|
|
9
9
|
import type { TerminalColors, TerminalTheme } from "./color.js";
|
|
10
10
|
import { type JSONOptions } from "./json.js";
|
|
@@ -45,7 +45,7 @@ export interface ConsoleOptions {
|
|
|
45
45
|
* Color encoding. Accepts a `ColorSystemName` (`"auto"`, `"truecolor"`,
|
|
46
46
|
* `"256"`, `"ansi"`, `"none"`), a `ColorDepth` enum value (use this for
|
|
47
47
|
* `WINDOWS`, which has no name), or `null` for no color. Default `"auto"`.
|
|
48
|
-
*
|
|
48
|
+
* Color only: an explicit depth, `null` included, keeps hyperlinks.
|
|
49
49
|
*/
|
|
50
50
|
colorSystem?: ColorSystemName | ColorDepth | null;
|
|
51
51
|
/**
|
|
@@ -74,8 +74,8 @@ export interface ConsoleOptions {
|
|
|
74
74
|
reducedMotion?: boolean;
|
|
75
75
|
/**
|
|
76
76
|
* The terminal this console draws on (`RenderOptions.terminal`), which
|
|
77
|
-
* every effect it draws resolves its
|
|
78
|
-
*
|
|
77
|
+
* every effect it draws resolves its colors on. Default: the one the
|
|
78
|
+
* color depth assumes.
|
|
79
79
|
*/
|
|
80
80
|
terminal?: TerminalColors;
|
|
81
81
|
/**
|
|
@@ -113,7 +113,7 @@ export interface ConsoleOptions {
|
|
|
113
113
|
stderr?: boolean;
|
|
114
114
|
file?: ConsoleSink;
|
|
115
115
|
/**
|
|
116
|
-
* Host facilities to consult for
|
|
116
|
+
* Host facilities to consult for color detection, size detection, and the
|
|
117
117
|
* default output sink. Defaults to the ambient `process`, or — where there
|
|
118
118
|
* is no `process` — an empty environment with no streams. Pass this to drive
|
|
119
119
|
* a `Console` deterministically, or to run one against a simulated terminal.
|
|
@@ -185,12 +185,12 @@ export declare class Console {
|
|
|
185
185
|
get isInteractive(): boolean;
|
|
186
186
|
get colorSystem(): ColorDepth | null;
|
|
187
187
|
/**
|
|
188
|
-
* Where this console writes: the
|
|
188
|
+
* Where this console writes: the color depth it draws at, whether it
|
|
189
189
|
* emits OSC 8 hyperlinks, and whether its reader asked for reduced motion,
|
|
190
190
|
* overrides applied — the value its output is
|
|
191
191
|
* encoded for, for anything that encodes on its behalf (`Live`).
|
|
192
192
|
*/
|
|
193
|
-
get destination():
|
|
193
|
+
get destination(): OutputTarget;
|
|
194
194
|
get file(): ConsoleSink;
|
|
195
195
|
get theme(): Theme;
|
|
196
196
|
get options(): RenderOptions & {
|
|
@@ -208,7 +208,7 @@ export declare class Console {
|
|
|
208
208
|
rule(title?: string, options?: RuleOptions): void;
|
|
209
209
|
printJson(json: string | object, options?: JSONOptions): void;
|
|
210
210
|
/**
|
|
211
|
-
*
|
|
211
|
+
* Keep `region` under everything this console writes until the returned
|
|
212
212
|
* call lets it go. One region at a time: a second would be erased and
|
|
213
213
|
* painted over by the first, so claiming one while another is held throws.
|
|
214
214
|
*/
|
package/dist/core/console.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Segment } from "./segment.js";
|
|
5
5
|
import { NULL_STYLE, DEFAULT_THEME } from "./style.js";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveOutputTarget } from "./color.js";
|
|
7
7
|
import { isDumbTerminal } from "./env.js";
|
|
8
8
|
import { encodeHtml } from "./export-html.js";
|
|
9
9
|
import { encodeSvg } from "./export-svg.js";
|
|
@@ -95,7 +95,7 @@ function ambientEnvironment() {
|
|
|
95
95
|
// bytes go — is a question about *that* stream. Selecting it once, here, is
|
|
96
96
|
// what makes the three answers agree. When each site re-selected for itself,
|
|
97
97
|
// one of them (size) silently didn't, and a `Console({ stderr: true })` keyed
|
|
98
|
-
// its
|
|
98
|
+
// its color to stderr and its width to stdout.
|
|
99
99
|
function boundStream(environment, useStderr) {
|
|
100
100
|
return useStderr ? environment.stderr : environment.stdout;
|
|
101
101
|
}
|
|
@@ -215,7 +215,7 @@ export class Console {
|
|
|
215
215
|
// [LAW:dataflow-not-control-flow] `isTTY` and `env` are forwarded
|
|
216
216
|
// unconditionally, so detection stays inside the console's injected
|
|
217
217
|
// environment rather than the ambient process's.
|
|
218
|
-
const resolved =
|
|
218
|
+
const resolved = resolveOutputTarget(options?.colorSystem === undefined ? "auto" : options.colorSystem, { isTTY: this._isTerminal, env: environment.env, reducedMotion: options?.reducedMotion, ...(options?.textOrder === undefined ? {} : { textOrder: options.textOrder }) });
|
|
219
219
|
// [LAW:single-enforcer] The console's one override, an explicit
|
|
220
220
|
// `hyperlinks`, is applied here and nowhere else; every write encodes for
|
|
221
221
|
// this value whole. [LAW:one-source-of-truth] The reader's motion
|
|
@@ -261,7 +261,7 @@ export class Console {
|
|
|
261
261
|
return this._destination.colorSystem;
|
|
262
262
|
}
|
|
263
263
|
/**
|
|
264
|
-
* Where this console writes: the
|
|
264
|
+
* Where this console writes: the color depth it draws at, whether it
|
|
265
265
|
* emits OSC 8 hyperlinks, and whether its reader asked for reduced motion,
|
|
266
266
|
* overrides applied — the value its output is
|
|
267
267
|
* encoded for, for anything that encodes on its behalf (`Live`).
|
|
@@ -534,7 +534,7 @@ export class Console {
|
|
|
534
534
|
}
|
|
535
535
|
// --- Live region ---
|
|
536
536
|
/**
|
|
537
|
-
*
|
|
537
|
+
* Keep `region` under everything this console writes until the returned
|
|
538
538
|
* call lets it go. One region at a time: a second would be erased and
|
|
539
539
|
* painted over by the first, so claiming one while another is held throws.
|
|
540
540
|
*/
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
* holds it as a character. `line-break` is a line ending, so content holds an LF
|
|
17
17
|
* in its place. `pictured` means nothing inside a span, so content holds the
|
|
18
18
|
* stand-in `pictureOf` gives in its place and the reader sees something was there.
|
|
19
|
-
* `
|
|
19
|
+
* `zeroWidth` is held in content and measured as nothing, and `wireText` decides
|
|
20
20
|
* from its neighbours whether it is written.
|
|
21
21
|
*
|
|
22
|
-
* Only `keep`, and a `
|
|
22
|
+
* Only `keep`, and a `zeroWidth` code point `wireText` lets by, reaches the wire. A
|
|
23
23
|
* raw `Segment` is not content, so what it holds of the others is deleted there.
|
|
24
24
|
*/
|
|
25
|
-
export type Disposition = "strip" | "keep" | "line-break" | "pictured" | "
|
|
25
|
+
export type Disposition = "strip" | "keep" | "line-break" | "pictured" | "zeroWidth";
|
|
26
26
|
/**
|
|
27
27
|
* The code points `first` to `last`, inclusive, and what is done with each. A
|
|
28
28
|
* `pictured` row carries what content shows in place of each of its code points.
|
|
@@ -24,7 +24,7 @@ const pictured = (first, last, picture) => ({ first, last, disposition: "picture
|
|
|
24
24
|
const controlPicture = (codePoint) => String.fromCharCode(0x2400 + codePoint);
|
|
25
25
|
const deletePicture = () => "\u2421";
|
|
26
26
|
const substitute = () => "\u2426";
|
|
27
|
-
const
|
|
27
|
+
const zeroWidth = (first, last) => ({ first, last, disposition: "zeroWidth" });
|
|
28
28
|
/**
|
|
29
29
|
* Ascending and disjoint, every Cc, Cf, Zl, Zp and Variation_Selector code point
|
|
30
30
|
* in exactly one row (`test/core/control-codes.test.ts`).
|
|
@@ -61,7 +61,7 @@ export const CONTROL_CODES = [
|
|
|
61
61
|
pictured(0x86, 0x9f, substitute),
|
|
62
62
|
// SOFT HYPHEN: a place a word may break, drawn as a hyphen only where one does.
|
|
63
63
|
// Terminals disagree on its cell, so it never reaches them.
|
|
64
|
-
|
|
64
|
+
zeroWidth(0xad, 0xad),
|
|
65
65
|
// The Arabic and Syriac number signs and other prepended concatenation marks,
|
|
66
66
|
// which draw a glyph.
|
|
67
67
|
keep(0x600, 0x605),
|
|
@@ -74,10 +74,10 @@ export const CONTROL_CODES = [
|
|
|
74
74
|
keep(0x890, 0x891),
|
|
75
75
|
keep(0x8e2, 0x8e2),
|
|
76
76
|
// The Mongolian free variation selectors.
|
|
77
|
-
|
|
77
|
+
zeroWidth(0x180b, 0x180d),
|
|
78
78
|
// MONGOLIAN VOWEL SEPARATOR, which shapes the vowel after it.
|
|
79
79
|
keep(0x180e, 0x180e),
|
|
80
|
-
|
|
80
|
+
zeroWidth(0x180f, 0x180f),
|
|
81
81
|
// ZWSP, a place a line may break (`wrap.ts`); ZWNJ, which Persian and Urdu spell
|
|
82
82
|
// with; ZWJ, for emoji and conjuncts; and the bidi marks LRM and RLM, which hold
|
|
83
83
|
// no state, so right-to-left text can use them. ZWJ's joining is Rich's width
|
|
@@ -97,7 +97,7 @@ export const CONTROL_CODES = [
|
|
|
97
97
|
// the text, Unicode deprecates them, and no terminal was found honouring one.
|
|
98
98
|
strip(0x206a, 0x206f),
|
|
99
99
|
// VARIATION SELECTOR-1 to 16: glyph variants, and text or emoji presentation.
|
|
100
|
-
|
|
100
|
+
zeroWidth(0xfe00, 0xfe0f),
|
|
101
101
|
// ZERO WIDTH NO-BREAK SPACE, the byte order mark, as a word joiner.
|
|
102
102
|
keep(0xfeff, 0xfeff),
|
|
103
103
|
// Interlinear annotation. No terminal draws ruby, the annotating text stays
|
|
@@ -113,9 +113,9 @@ export const CONTROL_CODES = [
|
|
|
113
113
|
// LANGUAGE TAG, deprecated.
|
|
114
114
|
strip(0xe0001, 0xe0001),
|
|
115
115
|
// The tag characters: an emoji subdivision flag, or text no reader can see.
|
|
116
|
-
|
|
116
|
+
zeroWidth(0xe0020, 0xe007f),
|
|
117
117
|
// The ideographic variation selectors: Japanese and Chinese glyph variants.
|
|
118
|
-
|
|
118
|
+
zeroWidth(0xe0100, 0xe01ef),
|
|
119
119
|
];
|
|
120
120
|
/** What content shows in place of `codePoint`, whose disposition is `pictured`. */
|
|
121
121
|
export function pictureOf(codePoint) {
|