@promptctl/rich-js 0.27.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 -6
- package/THIRD-PARTY-NOTICES +42 -0
- package/dist/core/animation.d.ts +65 -46
- package/dist/core/animation.js +91 -67
- package/dist/core/ansi.d.ts +19 -12
- package/dist/core/ansi.js +114 -36
- package/dist/core/bidi-data.d.ts +14 -0
- package/dist/core/bidi-data.js +385 -0
- package/dist/core/bidi.d.ts +89 -0
- package/dist/core/bidi.js +615 -0
- package/dist/core/box.d.ts +9 -1
- package/dist/core/box.js +11 -0
- package/dist/core/cell-widths.d.ts +3 -2
- package/dist/core/cell-widths.js +93 -93
- package/dist/core/cells.d.ts +20 -0
- package/dist/core/cells.js +94 -6
- package/dist/core/clock.d.ts +1 -1
- package/dist/core/color.d.ts +56 -57
- package/dist/core/color.js +79 -81
- package/dist/core/console.d.ts +24 -7
- package/dist/core/console.js +27 -8
- package/dist/core/control-codes.d.ts +61 -0
- package/dist/core/control-codes.js +157 -0
- package/dist/core/easing.d.ts +40 -40
- package/dist/core/easing.js +40 -40
- package/dist/core/env.d.ts +6 -0
- package/dist/core/env.js +9 -1
- package/dist/core/export-html.js +5 -4
- package/dist/core/export-lines.d.ts +13 -11
- package/dist/core/export-lines.js +19 -15
- package/dist/core/export-svg.d.ts +3 -3
- package/dist/core/export-svg.js +10 -9
- package/dist/core/json.js +9 -2
- package/dist/core/markup.js +5 -4
- 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 +68 -0
- package/dist/core/orient.js +224 -0
- package/dist/core/osc8.d.ts +12 -5
- package/dist/core/osc8.js +14 -7
- 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 +23 -19
- package/dist/core/protocol.d.ts +47 -26
- package/dist/core/protocol.js +31 -23
- package/dist/core/render.d.ts +19 -14
- package/dist/core/render.js +30 -17
- package/dist/core/seal.d.ts +26 -0
- package/dist/core/seal.js +75 -0
- package/dist/core/segment.d.ts +12 -4
- package/dist/core/segment.js +16 -6
- package/dist/core/strip.d.ts +83 -83
- package/dist/core/strip.js +70 -70
- package/dist/core/style.d.ts +46 -18
- package/dist/core/style.js +92 -56
- package/dist/core/text-order.d.ts +51 -0
- package/dist/core/text-order.js +50 -0
- package/dist/core/text.d.ts +12 -2
- package/dist/core/text.js +136 -90
- package/dist/core/timeline.d.ts +5 -5
- package/dist/core/timeline.js +11 -11
- package/dist/core/tween.d.ts +6 -6
- package/dist/core/tween.js +10 -10
- package/dist/core/view.d.ts +5 -5
- package/dist/core/view.js +15 -14
- package/dist/core/wrap.d.ts +24 -6
- package/dist/core/wrap.js +82 -16
- package/dist/host/app.d.ts +50 -9
- package/dist/host/app.js +120 -15
- package/dist/host/host-environment.d.ts +2 -2
- package/dist/host/host-environment.js +2 -2
- package/dist/host/index.d.ts +3 -2
- package/dist/host/index.js +1 -0
- package/dist/host/input.d.ts +42 -9
- package/dist/host/input.js +91 -7
- package/dist/host/terminal-colors.d.ts +18 -0
- package/dist/host/terminal-colors.js +46 -0
- package/dist/host/terminal-host.d.ts +4 -3
- package/dist/host/terminal-host.js +1 -1
- package/dist/index.d.ts +17 -16
- package/dist/index.js +11 -11
- 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.d.ts +1 -3
- package/dist/renderables/change.js +6 -8
- package/dist/renderables/effect.d.ts +88 -87
- package/dist/renderables/effect.js +124 -114
- package/dist/renderables/effects.d.ts +105 -76
- package/dist/renderables/effects.js +309 -176
- 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 +7 -16
- package/dist/renderables/frames.js +12 -27
- package/dist/renderables/glyph-effect.d.ts +22 -23
- package/dist/renderables/glyph-effect.js +43 -41
- package/dist/renderables/glyph-effects.d.ts +33 -14
- package/dist/renderables/glyph-effects.js +90 -22
- package/dist/renderables/html-entities.d.ts +1 -1
- package/dist/renderables/html-entities.js +1 -1
- package/dist/renderables/lifecycle.d.ts +8 -10
- package/dist/renderables/lifecycle.js +17 -18
- 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/markdown.js +4 -2
- package/dist/renderables/panel.js +7 -5
- package/dist/renderables/progress.d.ts +1 -1
- package/dist/renderables/progress.js +1 -1
- package/dist/renderables/progressBar.d.ts +3 -3
- package/dist/renderables/progressBar.js +21 -18
- 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 +9 -4
- package/dist/renderables/table.js +5 -4
- 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 +60 -29
- package/dist/template-bindings/animation-funcs.js +126 -43
- 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 +16 -14
- package/dist/template-bindings/index.js +17 -14
- package/dist/template-bindings/palette-funcs.d.ts +2 -2
- package/dist/template-bindings/palette-funcs.js +4 -4
- 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 +6 -5
- package/dist/themes/buildPalette.js +22 -22
- 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/index.js +1 -4
- package/dist/themes/data/textual-ansi.js +0 -143
- 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.d.ts +6 -8
- package/dist/themes/registry.js +6 -8
- package/dist/themes/terminalThemes.d.ts +4 -11
- package/dist/themes/terminalThemes.js +31 -47
- package/dist/widgets/button.d.ts +3 -3
- package/dist/widgets/button.js +8 -8
- package/dist/widgets/checkbox.d.ts +2 -2
- package/dist/widgets/checkbox.js +4 -4
- package/dist/widgets/dropdown.d.ts +3 -3
- package/dist/widgets/dropdown.js +7 -5
- 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 +4 -4
- package/dist/widgets/toggle.d.ts +4 -4
- package/dist/widgets/toggle.js +6 -6
- 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 +5 -4
package/dist/core/color.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Terminal color representation, parsing, downgrading, and ANSI code generation.
|
|
3
3
|
*/
|
|
4
|
+
import { isDumbTerminal } from "./env.js";
|
|
4
5
|
import { Memo, WeakMemo } from "./memo.js";
|
|
5
6
|
import { pattern } from "./pattern.js";
|
|
7
|
+
import { detectTextOrder } from "./text-order.js";
|
|
6
8
|
// --- ColorRgba ---
|
|
7
9
|
function hex2(byte) {
|
|
8
10
|
return byte.toString(16).padStart(2, "0");
|
|
9
11
|
}
|
|
10
|
-
// [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
|
|
11
13
|
// constructor asserts it and the string parser reports it, from this predicate.
|
|
12
14
|
function isByte(v) {
|
|
13
15
|
return Number.isInteger(v) && v >= 0 && v <= 255;
|
|
@@ -73,12 +75,12 @@ export class ColorRgba {
|
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
/**
|
|
76
|
-
* The surface a terminal draws a translucent
|
|
78
|
+
* The surface a terminal draws a translucent color over. A terminal cannot
|
|
77
79
|
* know what lies under its cells, so the SGR writer (`Style.toSgrCodes`), the
|
|
78
80
|
* exports that picture its output (`resolveLook`), the strip's seam test and
|
|
79
81
|
* the contrast choosers (`themes/colorMath`) all composite over this one
|
|
80
|
-
*
|
|
81
|
-
* the
|
|
82
|
+
* color. [LAW:one-source-of-truth] One constant, so
|
|
83
|
+
* the color text is chosen against is the color the writer draws.
|
|
82
84
|
*/
|
|
83
85
|
export const SURFACE_BLACK = new ColorRgba(0, 0, 0);
|
|
84
86
|
/**
|
|
@@ -115,7 +117,7 @@ function luminanceRatio(la, lb) {
|
|
|
115
117
|
// --- ColorTable ---
|
|
116
118
|
// [LAW:one-source-of-truth] The one distance every table scan ranks by, so
|
|
117
119
|
// `matchWhere`'s "nearest by the distance `match` uses" cannot drift, and
|
|
118
|
-
// `Effected` weighs a written
|
|
120
|
+
// `Effected` weighs a written color against `ColorSpec.matchOn` by it too.
|
|
119
121
|
export function rgbDistance(a, b) {
|
|
120
122
|
const dr = a.red - b.red;
|
|
121
123
|
const dg = a.green - b.green;
|
|
@@ -125,7 +127,7 @@ export function rgbDistance(a, b) {
|
|
|
125
127
|
/**
|
|
126
128
|
* An indexed palette: entry `i` of `colors` is terminal index `firstIndex + i`.
|
|
127
129
|
* `firstIndex` lets a table hold only the part of a palette a downgrade may
|
|
128
|
-
* choose (the 256-
|
|
130
|
+
* choose (the 256-color cube and grey ramp start at 16) while every index it
|
|
129
131
|
* reports is the terminal's own.
|
|
130
132
|
*/
|
|
131
133
|
export class ColorTable {
|
|
@@ -133,7 +135,7 @@ export class ColorTable {
|
|
|
133
135
|
/** Each entry's relative luminance. */
|
|
134
136
|
luminances;
|
|
135
137
|
firstIndex;
|
|
136
|
-
// Keyed by
|
|
138
|
+
// Keyed by colors a host computes without end (ramp stops, mixes), so bounded.
|
|
137
139
|
matchMemo = new Memo();
|
|
138
140
|
readableMemo = new Memo();
|
|
139
141
|
constructor(colors, firstIndex = 0) {
|
|
@@ -207,7 +209,7 @@ export class ColorTable {
|
|
|
207
209
|
}
|
|
208
210
|
/**
|
|
209
211
|
* The nearest entry to `value` (the distance `match` uses) among those
|
|
210
|
-
* `accept` takes, given each entry's
|
|
212
|
+
* `accept` takes, given each entry's color and terminal index; `undefined`
|
|
211
213
|
* when it takes none. Entries are offered nearest-first (ties to the lower
|
|
212
214
|
* index) and the first taken wins, so an expensive predicate runs only as
|
|
213
215
|
* far out as the answer. Uncached: the predicate is the caller's, and a
|
|
@@ -230,7 +232,7 @@ export var ColorDepth;
|
|
|
230
232
|
ColorDepth[ColorDepth["WINDOWS"] = 4] = "WINDOWS";
|
|
231
233
|
})(ColorDepth || (ColorDepth = {}));
|
|
232
234
|
/**
|
|
233
|
-
* How many
|
|
235
|
+
* How many colors a depth can name, as a rank. WINDOWS is a sixteen-color
|
|
234
236
|
* depth whose enum value sits above TRUECOLOR, so the enum's order is not this.
|
|
235
237
|
* STANDARD and WINDOWS share a rank: the same sixteen slots, drawn by
|
|
236
238
|
* different terminals, so each converts to the other by keeping the slot.
|
|
@@ -248,7 +250,7 @@ function fidelity(depth) {
|
|
|
248
250
|
return 3;
|
|
249
251
|
}
|
|
250
252
|
}
|
|
251
|
-
// The depths a
|
|
253
|
+
// The depths a color system is named for. Its keys and "auto" are the whole
|
|
252
254
|
// vocabulary: `ColorSystemName` is derived from them, so the type and the
|
|
253
255
|
// table cannot disagree. [LAW:one-source-of-truth]
|
|
254
256
|
const COLOR_SYSTEM_DEPTHS = {
|
|
@@ -257,11 +259,11 @@ const COLOR_SYSTEM_DEPTHS = {
|
|
|
257
259
|
ansi: ColorDepth.STANDARD,
|
|
258
260
|
none: null,
|
|
259
261
|
};
|
|
260
|
-
// [LAW:one-source-of-truth] What the environment says about
|
|
262
|
+
// [LAW:one-source-of-truth] What the environment says about color, by the
|
|
261
263
|
// value it says it with: FORCE_COLOR values (the chalk/supports-color
|
|
262
|
-
// convention), TERM_PROGRAM identifiers, and exact TERM names whose
|
|
264
|
+
// convention), TERM_PROGRAM identifiers, and exact TERM names whose color
|
|
263
265
|
// capability is known. A different vocabulary from `ColorSystemName`, so a
|
|
264
|
-
// 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`,
|
|
265
267
|
// so a value naming an `Object.prototype` member is unknown, not a function.
|
|
266
268
|
// `null` means "no color".
|
|
267
269
|
const ENV_DEPTHS = new Map([
|
|
@@ -297,7 +299,7 @@ const ENV_DEPTHS = new Map([
|
|
|
297
299
|
* in the env values, not in which checks execute.
|
|
298
300
|
*/
|
|
299
301
|
export function detectColorSystem(options = {}) {
|
|
300
|
-
// NO_COLOR and FORCE_COLOR are preferences about
|
|
302
|
+
// NO_COLOR and FORCE_COLOR are preferences about color, not facts about the
|
|
301
303
|
// terminal, so they sit outside the probe. NO_COLOR (any non-empty value)
|
|
302
304
|
// beats FORCE_COLOR; FORCE_COLOR beats TTY/TERM detection.
|
|
303
305
|
const noColor = envOf(options)["NO_COLOR"];
|
|
@@ -317,23 +319,15 @@ function forcedColorSystem(env) {
|
|
|
317
319
|
function envOf(options) {
|
|
318
320
|
return options.env ?? (typeof process !== "undefined" ? process.env : {});
|
|
319
321
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
* as Emacs' shell mode sets it. It takes no colour and nothing that moves the
|
|
323
|
-
* cursor.
|
|
324
|
-
*/
|
|
325
|
-
export function isDumbTerminal(env) {
|
|
326
|
-
const term = env["TERM"];
|
|
327
|
-
return term === "dumb" || term === "unknown";
|
|
322
|
+
function isTTYOf(options) {
|
|
323
|
+
return options.isTTY ?? (typeof process !== "undefined" ? (process.stdout?.isTTY ?? false) : false);
|
|
328
324
|
}
|
|
329
325
|
// What the destination can draw, preferences aside: TTY presence,
|
|
330
326
|
// TERM=dumb/unknown, COLORTERM, known terminal names, TERM patterns. `null`
|
|
331
327
|
// here means the destination takes no escapes at all.
|
|
332
328
|
function terminalColorSystem(options) {
|
|
333
329
|
const env = envOf(options);
|
|
334
|
-
|
|
335
|
-
(typeof process !== "undefined" ? (process.stdout?.isTTY ?? false) : false);
|
|
336
|
-
if (!isTTY)
|
|
330
|
+
if (!isTTYOf(options))
|
|
337
331
|
return null;
|
|
338
332
|
if (isDumbTerminal(env))
|
|
339
333
|
return null;
|
|
@@ -365,22 +359,25 @@ function terminalColorSystem(options) {
|
|
|
365
359
|
return ColorDepth.STANDARD;
|
|
366
360
|
}
|
|
367
361
|
/**
|
|
368
|
-
* Resolve a
|
|
362
|
+
* Resolve a color spec into an `OutputTarget`.
|
|
369
363
|
*
|
|
370
364
|
* [LAW:single-enforcer] The one place a spec becomes both facts. A hyperlink is
|
|
371
|
-
* not a
|
|
372
|
-
*
|
|
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
|
|
373
367
|
* terminal can take (no TTY, TERM=dumb: none) while NO_COLOR and FORCE_COLOR=0,
|
|
374
|
-
*
|
|
368
|
+
* color preferences, leave them alone. A FORCE_COLOR that forces color on
|
|
375
369
|
* declares the destination takes escapes, so it keeps links on a pipe too.
|
|
376
370
|
*/
|
|
377
|
-
export function
|
|
371
|
+
export function resolveOutputTarget(spec, options = {}) {
|
|
378
372
|
const reducedMotion = options.reducedMotion ?? false;
|
|
373
|
+
// Ahead of both arms: a color spec says nothing about order.
|
|
374
|
+
const textOrder = options.textOrder ?? detectTextOrder(envOf(options), isTTYOf(options));
|
|
379
375
|
if (spec !== "auto") {
|
|
380
376
|
return {
|
|
381
377
|
colorSystem: typeof spec === "string" ? resolveColorSystem(spec) : spec,
|
|
382
378
|
hyperlinks: true,
|
|
383
379
|
reducedMotion,
|
|
380
|
+
textOrder,
|
|
384
381
|
};
|
|
385
382
|
}
|
|
386
383
|
return {
|
|
@@ -388,10 +385,11 @@ export function resolveDestination(spec, options = {}) {
|
|
|
388
385
|
hyperlinks: (forcedColorSystem(envOf(options)) ?? null) !== null ||
|
|
389
386
|
terminalColorSystem(options) !== null,
|
|
390
387
|
reducedMotion,
|
|
388
|
+
textOrder,
|
|
391
389
|
};
|
|
392
390
|
}
|
|
393
391
|
/**
|
|
394
|
-
* Resolve a
|
|
392
|
+
* Resolve a color system name into a `ColorDepth` (or `null` for no color).
|
|
395
393
|
*
|
|
396
394
|
* `"auto"` triggers env-based detection; every other name is a fixed depth.
|
|
397
395
|
* A name outside the vocabulary — reachable only from untyped JavaScript —
|
|
@@ -431,12 +429,12 @@ export class ColorSpec {
|
|
|
431
429
|
return this.type === ColorDepth.DEFAULT;
|
|
432
430
|
}
|
|
433
431
|
/**
|
|
434
|
-
* The
|
|
432
|
+
* The color every terminal draws this spec as, where that is fixed — before
|
|
435
433
|
* any alpha is flattened, so a translucent value is drawn composited over
|
|
436
434
|
* its ground (`flattenAlpha`) and should be measured that way: a
|
|
437
|
-
* truecolor value, or a 256-
|
|
435
|
+
* truecolor value, or a 256-color cube or grey-ramp entry (xterm fixes
|
|
438
436
|
* indices 16–255, and `fromAnsi` types only those as EIGHT_BIT). ANSI 0–15,
|
|
439
|
-
* the default
|
|
437
|
+
* the default color and a blend reaching either are the terminal theme's
|
|
440
438
|
* own, so they have none.
|
|
441
439
|
*/
|
|
442
440
|
get fixedValue() {
|
|
@@ -555,20 +553,20 @@ export class ColorSpec {
|
|
|
555
553
|
return ColorSpec.fromRgba(new ColorRgba(r, g, b));
|
|
556
554
|
}
|
|
557
555
|
/**
|
|
558
|
-
* The
|
|
559
|
-
* parses to. Two fixed
|
|
560
|
-
* 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
|
|
561
559
|
* an end draws the mix from it: exported under a theme whose `blue` is
|
|
562
560
|
* #61afef, a mix with `blue` starts from #61afef. A terminal is told its RGB
|
|
563
561
|
* under the standard table, the only one a render has.
|
|
564
562
|
*
|
|
565
|
-
* Each end is one opaque
|
|
563
|
+
* Each end is one opaque color: `default` is no color to mix, and a
|
|
566
564
|
* translucent end has no one shade until it is laid on a ground.
|
|
567
565
|
*/
|
|
568
566
|
static blend(from, to, t) {
|
|
569
567
|
for (const end of [from, to]) {
|
|
570
568
|
if (end.isDefault)
|
|
571
|
-
throw new ColorParseError(`A blend cannot mix "default", which is no
|
|
569
|
+
throw new ColorParseError(`A blend cannot mix "default", which is no color`);
|
|
572
570
|
if (end.value !== undefined && end.value.alpha < 1) {
|
|
573
571
|
throw new ColorParseError(`A blend's ends are opaque; "${end.name}" is translucent`);
|
|
574
572
|
}
|
|
@@ -591,21 +589,21 @@ export class ColorSpec {
|
|
|
591
589
|
}
|
|
592
590
|
/**
|
|
593
591
|
* The spec that draws `value` nearest to it at `depth` on a terminal known
|
|
594
|
-
* to show `theme`, as the
|
|
592
|
+
* to show `theme`, as the color of the glyph (`foreground`) or of the
|
|
595
593
|
* ground. Where `downgrade` knows no terminal, and so rounds only against
|
|
596
|
-
*
|
|
597
|
-
* sixteen), this rounds against every
|
|
598
|
-
* look `theme` fixes: the default
|
|
599
|
-
*
|
|
600
|
-
* moved a little is drawn as the
|
|
601
|
-
* 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.
|
|
602
600
|
*
|
|
603
|
-
* `value` is opaque: a translucent
|
|
601
|
+
* `value` is opaque: a translucent color has no one look until it is laid
|
|
604
602
|
* on a ground (`flattenAlpha`).
|
|
605
603
|
*/
|
|
606
604
|
static matchOn(value, depth, theme, foreground) {
|
|
607
605
|
if (value.alpha < 1)
|
|
608
|
-
throw new RangeError(`matchOn rounds an opaque
|
|
606
|
+
throw new RangeError(`matchOn rounds an opaque color; got alpha ${value.alpha}`);
|
|
609
607
|
if (depth === ColorDepth.TRUECOLOR)
|
|
610
608
|
return ColorSpec.fromRgba(value);
|
|
611
609
|
if (depth === ColorDepth.DEFAULT)
|
|
@@ -623,23 +621,23 @@ export class ColorSpec {
|
|
|
623
621
|
return candidates.reduce((best, next) => (rgbDistance(next[1], value) < rgbDistance(best[1], value) ? next : best))[0];
|
|
624
622
|
}
|
|
625
623
|
/**
|
|
626
|
-
* Every
|
|
624
|
+
* Every color `depth` writes by index, each with the color a terminal
|
|
627
625
|
* known to show `theme` draws it in, lowest index first: the theme's
|
|
628
|
-
* sixteen, and at 256
|
|
629
|
-
* drawn alike as glyph and as ground, which the default
|
|
630
|
-
* it is not among them. Truecolor writes a
|
|
631
|
-
* 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
|
|
632
630
|
* `matchOn` rounds to, but for the default, read off the same two tables.
|
|
633
631
|
*/
|
|
634
632
|
static indexed(depth, theme) {
|
|
635
633
|
return indexedMemo.get(theme, () => new Memo()).get(`${depth}`, () => listIndexed(depth, theme));
|
|
636
634
|
}
|
|
637
635
|
/**
|
|
638
|
-
* 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
|
|
639
637
|
* written spec draws on `theme`, to the opaque `now`: `matchOn`'s — or
|
|
640
638
|
* none, where the written spec is as near `now` as that match. A move the
|
|
641
|
-
* depth cannot show is no move, so below truecolor a
|
|
642
|
-
* 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,
|
|
643
641
|
* the cube — keeps the spec it was written in.
|
|
644
642
|
*/
|
|
645
643
|
static matchMove(was, now, depth, theme, foreground) {
|
|
@@ -655,7 +653,7 @@ export class ColorSpec {
|
|
|
655
653
|
}
|
|
656
654
|
// --- private ---
|
|
657
655
|
performDowngrade(targetSystem) {
|
|
658
|
-
// The
|
|
656
|
+
// The color as the terminal this depth assumes draws it: a blend's named
|
|
659
657
|
// ends are the Windows console's own at WINDOWS.
|
|
660
658
|
const triplet = this.getTruecolor(resolveTerminal(undefined, targetSystem));
|
|
661
659
|
switch (targetSystem) {
|
|
@@ -664,7 +662,7 @@ export class ColorSpec {
|
|
|
664
662
|
case ColorDepth.STANDARD:
|
|
665
663
|
case ColorDepth.WINDOWS: {
|
|
666
664
|
// An ANSI slot is already one of the sixteen either depth writes; only
|
|
667
|
-
// a fixed
|
|
665
|
+
// a fixed color is matched against the depth's table, as Rich does.
|
|
668
666
|
const index = this.number !== undefined && this.number < 16 ? this.number : downgradeTable(targetSystem).match(triplet);
|
|
669
667
|
return new ColorSpec(`color(${index})`, targetSystem, index);
|
|
670
668
|
}
|
|
@@ -675,7 +673,7 @@ export class ColorSpec {
|
|
|
675
673
|
}
|
|
676
674
|
}
|
|
677
675
|
}
|
|
678
|
-
/** The cube or grey-ramp entry nearest `value`, and its
|
|
676
|
+
/** The cube or grey-ramp entry nearest `value`, and its color. */
|
|
679
677
|
function cubeCandidate(value) {
|
|
680
678
|
const index = EIGHT_BIT_DOWNGRADE_TABLE.match(value);
|
|
681
679
|
return [ColorSpec.fromAnsi(index), EIGHT_BIT_DOWNGRADE_TABLE.get(index)];
|
|
@@ -701,7 +699,7 @@ function mix(from, to, t, theme) {
|
|
|
701
699
|
return blendRgb(from.getTruecolor(theme), to.getTruecolor(theme), t);
|
|
702
700
|
}
|
|
703
701
|
// How a blend spells an end: by what it draws as, so every spelling of one
|
|
704
|
-
//
|
|
702
|
+
// color ("blue", "color(4)", an EIGHT_BIT 4) gives the blend one name.
|
|
705
703
|
function blendTerm(end) {
|
|
706
704
|
return end.fixedValue?.hex ?? (end.number !== undefined ? `color(${end.number})` : end.name);
|
|
707
705
|
}
|
|
@@ -804,8 +802,8 @@ function parseByte(key, digits, field) {
|
|
|
804
802
|
return n;
|
|
805
803
|
}
|
|
806
804
|
// --- Utility functions ---
|
|
807
|
-
// [LAW:single-enforcer] The hex
|
|
808
|
-
// 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
|
|
809
807
|
// reference, a template argument — becomes one through the three parsers below,
|
|
810
808
|
// and each is this check at the lengths it admits. Each digit pair is a byte, so
|
|
811
809
|
// the grammar holding is what keeps `ColorRgba`'s channels in range.
|
|
@@ -816,12 +814,12 @@ const HEX_GRAMMARS = { 6: "RRGGBB", 8: "RRGGBBAA" };
|
|
|
816
814
|
function hexColor(input, lead, digits, lengths) {
|
|
817
815
|
if (!lengths.includes(digits.length) || !HEX_DIGITS_RE.test(digits)) {
|
|
818
816
|
const expected = lengths.map((n) => lead + HEX_GRAMMARS[n]).join(" or ");
|
|
819
|
-
throw new ColorParseError(`Invalid hex
|
|
817
|
+
throw new ColorParseError(`Invalid hex color ${JSON.stringify(input)} (expected ${expected})`);
|
|
820
818
|
}
|
|
821
819
|
const byte = (at) => parseInt(digits.slice(at, at + 2), 16);
|
|
822
820
|
return new ColorRgba(byte(0), byte(2), byte(4), digits.length === 8 ? byte(6) / 255 : 1);
|
|
823
821
|
}
|
|
824
|
-
/** Six hex digits, no `#`, as an opaque
|
|
822
|
+
/** Six hex digits, no `#`, as an opaque color. @throws {ColorParseError} on anything else. */
|
|
825
823
|
export function parseRgbHex(hex) {
|
|
826
824
|
return hexColor(hex, "", hex, [6]);
|
|
827
825
|
}
|
|
@@ -841,7 +839,7 @@ export function blendRgb(color1, color2, crossFade = 0.5) {
|
|
|
841
839
|
}
|
|
842
840
|
// --- TerminalTheme ---
|
|
843
841
|
/**
|
|
844
|
-
* 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
|
|
845
843
|
* against.
|
|
846
844
|
*/
|
|
847
845
|
export class TerminalColors {
|
|
@@ -855,17 +853,17 @@ export class TerminalColors {
|
|
|
855
853
|
// [LAW:parse-dont-validate] Every reader indexes `ansiColors` 0–15 as the
|
|
856
854
|
// terminal's sixteen, so a theme is the proof it holds exactly those.
|
|
857
855
|
if (ansiColors.firstIndex !== 0 || ansiColors.size !== 16) {
|
|
858
|
-
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}`);
|
|
859
857
|
}
|
|
860
858
|
}
|
|
861
859
|
}
|
|
862
860
|
/**
|
|
863
|
-
* A terminal theme — surface/foreground baseline, the sixteen ANSI
|
|
861
|
+
* A terminal theme — surface/foreground baseline, the sixteen ANSI colors,
|
|
864
862
|
* and a semantic palette.
|
|
865
863
|
*
|
|
866
|
-
* **`ansiColors` is the theme's own sixteen
|
|
864
|
+
* **`ansiColors` is the theme's own sixteen colors**, the shades a terminal
|
|
867
865
|
* showing this theme draws `red`, `blue` and the rest in. `ColorSpec.parse("red")`
|
|
868
|
-
* is ANSI
|
|
866
|
+
* is ANSI color 1 under every theme; which red that is, is the theme's to say,
|
|
869
867
|
* as it is in Rich, where each `TerminalTheme` carries its own table.
|
|
870
868
|
*/
|
|
871
869
|
export class TerminalTheme extends TerminalColors {
|
|
@@ -916,8 +914,8 @@ function build256Table() {
|
|
|
916
914
|
}
|
|
917
915
|
/**
|
|
918
916
|
* The Windows console's own sixteen (its default Campbell scheme), in ANSI
|
|
919
|
-
* index order: a WINDOWS
|
|
920
|
-
* 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.
|
|
921
919
|
*/
|
|
922
920
|
function buildWindowsTable() {
|
|
923
921
|
return [
|
|
@@ -942,8 +940,8 @@ function buildWindowsTable() {
|
|
|
942
940
|
export const STANDARD_TABLE = new ColorTable(buildStandard16());
|
|
943
941
|
export const EIGHT_BIT_TABLE = new ColorTable(build256Table());
|
|
944
942
|
/**
|
|
945
|
-
* What a downgrade to 256
|
|
946
|
-
* 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
|
|
947
945
|
* every theme redefines, so their RGB is unknown and a match against them is
|
|
948
946
|
* a guess; Python Rich never picks them either.
|
|
949
947
|
*/
|
|
@@ -952,18 +950,18 @@ export const WINDOWS_TABLE = new ColorTable(buildWindowsTable());
|
|
|
952
950
|
// --- Internal fallback terminals ---
|
|
953
951
|
//
|
|
954
952
|
// [LAW:one-way-deps] Preset themes (DEFAULT_TERMINAL_THEME, MONOKAI, NORD, ...)
|
|
955
|
-
// live in `src/themes/terminalThemes.ts` because they
|
|
956
|
-
//
|
|
953
|
+
// live in `src/themes/terminalThemes.ts` because they hold the registry's
|
|
954
|
+
// palettes. Keeping them out of `core/color.ts` makes the dependency strictly
|
|
957
955
|
// `themes/* -> core/color`, with no runtime back-edge.
|
|
958
956
|
//
|
|
959
957
|
// `getTruecolor()` retains a fallback for callers that omit `theme`: the
|
|
960
|
-
// terminal a
|
|
958
|
+
// terminal a color's depth assumes, its own sixteen and no palette, which the
|
|
961
959
|
// lookups it serves never read.
|
|
962
960
|
const INTERNAL_DEFAULT_TERMINAL = new TerminalColors(new ColorRgba(0, 0, 0), new ColorRgba(255, 255, 255), STANDARD_TABLE);
|
|
963
|
-
/** The Windows console in its default Campbell scheme: a WINDOWS
|
|
961
|
+
/** The Windows console in its default Campbell scheme: a WINDOWS color's terminal. */
|
|
964
962
|
const WINDOWS_CONSOLE_TERMINAL = new TerminalColors(WINDOWS_TABLE.get(0), WINDOWS_TABLE.get(7), WINDOWS_TABLE);
|
|
965
963
|
/**
|
|
966
|
-
* The terminal a
|
|
964
|
+
* The terminal a color at `depth` is drawn by: `theme`, or when a caller names
|
|
967
965
|
* none, the one the depth assumes — the Windows console at WINDOWS, the VGA
|
|
968
966
|
* sixteen otherwise — for `ColorSpec.getTruecolor` and the contrast measurement
|
|
969
967
|
* that reads it. (Widgets fall back to `DEFAULT_TERMINAL_THEME`, which carries a
|
|
@@ -973,9 +971,9 @@ export function resolveTerminal(theme, depth) {
|
|
|
973
971
|
return theme ?? (depth === ColorDepth.WINDOWS ? WINDOWS_CONSOLE_TERMINAL : INTERNAL_DEFAULT_TERMINAL);
|
|
974
972
|
}
|
|
975
973
|
/**
|
|
976
|
-
* The table a downgrade to `depth` rounds a fixed
|
|
977
|
-
* [LAW:one-source-of-truth] `ColorSpec.downgrade` picks the index a
|
|
978
|
-
* 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
|
|
979
977
|
* writer rounds to those same indices.
|
|
980
978
|
*/
|
|
981
979
|
export function downgradeTable(depth) {
|
package/dist/core/console.d.ts
CHANGED
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Style, Theme } from "./style.js";
|
|
5
5
|
import { ColorDepth } from "./color.js";
|
|
6
|
-
import type {
|
|
6
|
+
import type { TextOrder } from "./text-order.js";
|
|
7
|
+
import type { ColorSystemName, OutputTarget } from "./color.js";
|
|
7
8
|
import type { Env } from "./env.js";
|
|
8
|
-
import type { TerminalTheme } from "./color.js";
|
|
9
|
+
import type { TerminalColors, TerminalTheme } from "./color.js";
|
|
9
10
|
import { type JSONOptions } from "./json.js";
|
|
10
11
|
import type { Highlighter } from "./highlighter.js";
|
|
11
12
|
import { type RuleOptions } from "../renderables/rule.js";
|
|
@@ -44,7 +45,7 @@ export interface ConsoleOptions {
|
|
|
44
45
|
* Color encoding. Accepts a `ColorSystemName` (`"auto"`, `"truecolor"`,
|
|
45
46
|
* `"256"`, `"ansi"`, `"none"`), a `ColorDepth` enum value (use this for
|
|
46
47
|
* `WINDOWS`, which has no name), or `null` for no color. Default `"auto"`.
|
|
47
|
-
*
|
|
48
|
+
* Color only: an explicit depth, `null` included, keeps hyperlinks.
|
|
48
49
|
*/
|
|
49
50
|
colorSystem?: ColorSystemName | ColorDepth | null;
|
|
50
51
|
/**
|
|
@@ -53,6 +54,8 @@ export interface ConsoleOptions {
|
|
|
53
54
|
* TERM=dumb: false). `false` with `colorSystem: null` writes plain text.
|
|
54
55
|
*/
|
|
55
56
|
hyperlinks?: boolean;
|
|
57
|
+
/** What the output's destination does with direction. Default: what `detectTextOrder` finds. */
|
|
58
|
+
textOrder?: TextOrder;
|
|
56
59
|
/**
|
|
57
60
|
* The terminal can draw only ASCII: boxes, rules, tree guides and widget
|
|
58
61
|
* marks draw with ASCII characters instead of line-drawing glyphs. A
|
|
@@ -69,6 +72,12 @@ export interface ConsoleOptions {
|
|
|
69
72
|
* it in; nothing here reads the environment for it. Default false.
|
|
70
73
|
*/
|
|
71
74
|
reducedMotion?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* The terminal this console draws on (`RenderOptions.terminal`), which
|
|
77
|
+
* every effect it draws resolves its colors on. Default: the one the
|
|
78
|
+
* color depth assumes.
|
|
79
|
+
*/
|
|
80
|
+
terminal?: TerminalColors;
|
|
72
81
|
/**
|
|
73
82
|
* Static width (cells). Ignored when `getSize` is provided. Falls back to
|
|
74
83
|
* the `COLUMNS` env var / the bound stream's `columns` / 80.
|
|
@@ -104,7 +113,7 @@ export interface ConsoleOptions {
|
|
|
104
113
|
stderr?: boolean;
|
|
105
114
|
file?: ConsoleSink;
|
|
106
115
|
/**
|
|
107
|
-
* Host facilities to consult for
|
|
116
|
+
* Host facilities to consult for color detection, size detection, and the
|
|
108
117
|
* default output sink. Defaults to the ambient `process`, or — where there
|
|
109
118
|
* is no `process` — an empty environment with no streams. Pass this to drive
|
|
110
119
|
* a `Console` deterministically, or to run one against a simulated terminal.
|
|
@@ -149,6 +158,7 @@ export declare class Console {
|
|
|
149
158
|
private readonly _lastLogTime;
|
|
150
159
|
private readonly _style;
|
|
151
160
|
private readonly _isTerminal;
|
|
161
|
+
private readonly _attended;
|
|
152
162
|
private readonly _interactive;
|
|
153
163
|
private readonly _file;
|
|
154
164
|
private readonly _stream;
|
|
@@ -156,6 +166,7 @@ export declare class Console {
|
|
|
156
166
|
private readonly _markup;
|
|
157
167
|
private readonly _highlight;
|
|
158
168
|
private readonly _theme;
|
|
169
|
+
private readonly _terminal;
|
|
159
170
|
private readonly _onStyleError;
|
|
160
171
|
private readonly _asciiOnly;
|
|
161
172
|
private readonly _highlighter;
|
|
@@ -174,12 +185,12 @@ export declare class Console {
|
|
|
174
185
|
get isInteractive(): boolean;
|
|
175
186
|
get colorSystem(): ColorDepth | null;
|
|
176
187
|
/**
|
|
177
|
-
* Where this console writes: the
|
|
188
|
+
* Where this console writes: the color depth it draws at, whether it
|
|
178
189
|
* emits OSC 8 hyperlinks, and whether its reader asked for reduced motion,
|
|
179
190
|
* overrides applied — the value its output is
|
|
180
191
|
* encoded for, for anything that encodes on its behalf (`Live`).
|
|
181
192
|
*/
|
|
182
|
-
get destination():
|
|
193
|
+
get destination(): OutputTarget;
|
|
183
194
|
get file(): ConsoleSink;
|
|
184
195
|
get theme(): Theme;
|
|
185
196
|
get options(): RenderOptions & {
|
|
@@ -188,10 +199,16 @@ export declare class Console {
|
|
|
188
199
|
print(...args: unknown[]): void;
|
|
189
200
|
private _draw;
|
|
190
201
|
log(...args: unknown[]): void;
|
|
202
|
+
/**
|
|
203
|
+
* Sounds the terminal's bell, Rich's `Console.bell`, for whoever is at it: a
|
|
204
|
+
* pipe, a dumb terminal and a capture get nothing. It goes straight to the sink
|
|
205
|
+
* because a bell moves no cursor, and a live region would repaint its frame.
|
|
206
|
+
*/
|
|
207
|
+
bell(): void;
|
|
191
208
|
rule(title?: string, options?: RuleOptions): void;
|
|
192
209
|
printJson(json: string | object, options?: JSONOptions): void;
|
|
193
210
|
/**
|
|
194
|
-
*
|
|
211
|
+
* Keep `region` under everything this console writes until the returned
|
|
195
212
|
* call lets it go. One region at a time: a second would be erased and
|
|
196
213
|
* painted over by the first, so claiming one while another is held throws.
|
|
197
214
|
*/
|
package/dist/core/console.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
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
|
+
import { isDumbTerminal } from "./env.js";
|
|
7
8
|
import { encodeHtml } from "./export-html.js";
|
|
8
9
|
import { encodeSvg } from "./export-svg.js";
|
|
9
10
|
import { RichText } from "./text.js";
|
|
@@ -17,6 +18,7 @@ import { ReprHighlighter, NullHighlighter } from "./highlighter.js";
|
|
|
17
18
|
// rather than being restated here; see `rule()`.
|
|
18
19
|
import { Rule } from "../renderables/rule.js";
|
|
19
20
|
import { segmentsToString, shownOn } from "./render.js";
|
|
21
|
+
import { sealed } from "./seal.js";
|
|
20
22
|
import { placeBlock } from "./place.js";
|
|
21
23
|
import { activePass, isRenderable, measure, render } from "./protocol.js";
|
|
22
24
|
import { ListState, State, refuseRenderWrite } from "./state.js";
|
|
@@ -93,7 +95,7 @@ function ambientEnvironment() {
|
|
|
93
95
|
// bytes go — is a question about *that* stream. Selecting it once, here, is
|
|
94
96
|
// what makes the three answers agree. When each site re-selected for itself,
|
|
95
97
|
// one of them (size) silently didn't, and a `Console({ stderr: true })` keyed
|
|
96
|
-
// its
|
|
98
|
+
// its color to stderr and its width to stdout.
|
|
97
99
|
function boundStream(environment, useStderr) {
|
|
98
100
|
return useStderr ? environment.stderr : environment.stdout;
|
|
99
101
|
}
|
|
@@ -181,6 +183,7 @@ export class Console {
|
|
|
181
183
|
_lastLogTime = new State(null);
|
|
182
184
|
_style;
|
|
183
185
|
_isTerminal;
|
|
186
|
+
_attended;
|
|
184
187
|
_interactive;
|
|
185
188
|
_file;
|
|
186
189
|
// [LAW:one-source-of-truth] The resolved output stream, not the `stderr`
|
|
@@ -191,6 +194,7 @@ export class Console {
|
|
|
191
194
|
_markup;
|
|
192
195
|
_highlight;
|
|
193
196
|
_theme;
|
|
197
|
+
_terminal;
|
|
194
198
|
_onStyleError;
|
|
195
199
|
_asciiOnly;
|
|
196
200
|
_highlighter;
|
|
@@ -211,7 +215,7 @@ export class Console {
|
|
|
211
215
|
// [LAW:dataflow-not-control-flow] `isTTY` and `env` are forwarded
|
|
212
216
|
// unconditionally, so detection stays inside the console's injected
|
|
213
217
|
// environment rather than the ambient process's.
|
|
214
|
-
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 }) });
|
|
215
219
|
// [LAW:single-enforcer] The console's one override, an explicit
|
|
216
220
|
// `hyperlinks`, is applied here and nowhere else; every write encodes for
|
|
217
221
|
// this value whole. [LAW:one-source-of-truth] The reader's motion
|
|
@@ -223,9 +227,12 @@ export class Console {
|
|
|
223
227
|
// [LAW:no-ambient-temporal-coupling] The theme is assigned before the
|
|
224
228
|
// style, because the console's own style may be one of the theme's names.
|
|
225
229
|
this._theme = options?.theme ?? DEFAULT_THEME;
|
|
230
|
+
this._terminal = options?.terminal;
|
|
226
231
|
this._style = this._theme.resolve(options?.style ?? NULL_STYLE);
|
|
227
|
-
// Rich's rule: a terminal is interactive unless it is a dumb one.
|
|
228
|
-
|
|
232
|
+
// Rich's rule: a terminal is interactive unless it is a dumb one. Forcing that
|
|
233
|
+
// is animation policy, and says nothing of who is at the terminal.
|
|
234
|
+
this._attended = this._isTerminal && !isDumbTerminal(environment.env);
|
|
235
|
+
this._interactive = options?.forceInteractive ?? this._attended;
|
|
229
236
|
this._file = options?.file;
|
|
230
237
|
this._record = options?.record ?? false;
|
|
231
238
|
this._markup = options?.markup !== false;
|
|
@@ -254,7 +261,7 @@ export class Console {
|
|
|
254
261
|
return this._destination.colorSystem;
|
|
255
262
|
}
|
|
256
263
|
/**
|
|
257
|
-
* Where this console writes: the
|
|
264
|
+
* Where this console writes: the color depth it draws at, whether it
|
|
258
265
|
* emits OSC 8 hyperlinks, and whether its reader asked for reduced motion,
|
|
259
266
|
* overrides applied — the value its output is
|
|
260
267
|
* encoded for, for anything that encodes on its behalf (`Live`).
|
|
@@ -290,6 +297,8 @@ export class Console {
|
|
|
290
297
|
theme: this._theme,
|
|
291
298
|
onStyleError: this._onStyleError,
|
|
292
299
|
colorSystem: this._destination.colorSystem,
|
|
300
|
+
textOrder: this._destination.textOrder,
|
|
301
|
+
terminal: this._terminal,
|
|
293
302
|
markup: this._markup,
|
|
294
303
|
highlight: this._highlight,
|
|
295
304
|
highlighter: this._highlighter,
|
|
@@ -495,6 +504,16 @@ export class Console {
|
|
|
495
504
|
// stamp, so the next row's must show.
|
|
496
505
|
this._lastLogTime.set(stamped);
|
|
497
506
|
}
|
|
507
|
+
/**
|
|
508
|
+
* Sounds the terminal's bell, Rich's `Console.bell`, for whoever is at it: a
|
|
509
|
+
* pipe, a dumb terminal and a capture get nothing. It goes straight to the sink
|
|
510
|
+
* because a bell moves no cursor, and a live region would repaint its frame.
|
|
511
|
+
*/
|
|
512
|
+
bell() {
|
|
513
|
+
refuseRenderWrite(this._madeIn);
|
|
514
|
+
if (this._attended && this._capture.get() === null)
|
|
515
|
+
this.file.write("\x07");
|
|
516
|
+
}
|
|
498
517
|
// [LAW:one-source-of-truth] `RuleOptions` is `Rule`'s, not a restatement of
|
|
499
518
|
// it. `console.ts` used to declare its own copy and field-by-field forward
|
|
500
519
|
// into this constructor, which made a second map of one shape — identical
|
|
@@ -515,7 +534,7 @@ export class Console {
|
|
|
515
534
|
}
|
|
516
535
|
// --- Live region ---
|
|
517
536
|
/**
|
|
518
|
-
*
|
|
537
|
+
* Keep `region` under everything this console writes until the returned
|
|
519
538
|
* call lets it go. One region at a time: a second would be erased and
|
|
520
539
|
* painted over by the first, so claiming one while another is held throws.
|
|
521
540
|
*/
|
|
@@ -547,7 +566,7 @@ export class Console {
|
|
|
547
566
|
}
|
|
548
567
|
// --- Export (when record:true) ---
|
|
549
568
|
exportText({ clear = true } = {}) {
|
|
550
|
-
const text = this._recorded.get().map((s) => s.text).join("");
|
|
569
|
+
const text = [...sealed(this._recorded.get(), "plain")].map((s) => s.text).join("");
|
|
551
570
|
if (clear)
|
|
552
571
|
this._recorded.set([]);
|
|
553
572
|
return text;
|