@promptctl/rich-js 0.17.0 → 0.18.1
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 +13 -26
- package/dist/core/anchor.d.ts +45 -0
- package/dist/core/anchor.js +39 -0
- package/dist/core/ansi.d.ts +65 -0
- package/dist/core/ansi.js +231 -0
- package/dist/core/box.d.ts +0 -1
- package/dist/core/box.js +6 -18
- package/dist/core/cells.d.ts +16 -5
- package/dist/core/cells.js +31 -10
- package/dist/core/color.d.ts +4 -8
- package/dist/core/color.js +28 -19
- package/dist/core/console.d.ts +13 -4
- package/dist/core/console.js +91 -36
- package/dist/core/export-html.d.ts +40 -5
- package/dist/core/export-html.js +111 -17
- package/dist/core/markup.d.ts +27 -5
- package/dist/core/markup.js +282 -170
- package/dist/core/measure.d.ts +1 -1
- package/dist/core/measure.js +2 -1
- package/dist/core/place.d.ts +30 -0
- package/dist/core/place.js +51 -0
- package/dist/core/pretty.d.ts +3 -0
- package/dist/core/pretty.js +5 -1
- package/dist/core/protocol.d.ts +136 -6
- package/dist/core/protocol.js +64 -2
- package/dist/core/render.d.ts +2 -2
- package/dist/core/render.js +2 -2
- package/dist/core/segment.d.ts +23 -4
- package/dist/core/segment.js +75 -16
- package/dist/core/spinnerData.d.ts +2 -0
- package/dist/core/spinnerData.js +3 -1
- package/dist/core/strip.d.ts +3 -7
- package/dist/core/strip.js +32 -35
- package/dist/core/style.d.ts +25 -0
- package/dist/core/style.js +61 -89
- package/dist/core/text.d.ts +16 -15
- package/dist/core/text.js +62 -76
- package/dist/host/app.d.ts +121 -0
- package/dist/host/app.js +255 -0
- package/dist/host/host-environment.d.ts +26 -0
- package/dist/host/host-environment.js +44 -0
- package/dist/host/index.d.ts +4 -2
- package/dist/host/index.js +2 -1
- package/dist/host/terminal-host.d.ts +43 -7
- package/dist/host/terminal-host.js +57 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +4 -1
- package/dist/node/terminal-host.d.ts +31 -2
- package/dist/node/terminal-host.js +69 -2
- package/dist/node/traceback.d.ts +16 -6
- package/dist/node/traceback.js +30 -8
- package/dist/renderables/align.d.ts +2 -2
- package/dist/renderables/align.js +6 -19
- package/dist/renderables/columns.js +4 -20
- package/dist/renderables/embed.d.ts +50 -0
- package/dist/renderables/embed.js +71 -0
- package/dist/renderables/group.js +3 -1
- package/dist/renderables/layout.js +31 -34
- package/dist/renderables/live.d.ts +6 -3
- package/dist/renderables/live.js +89 -45
- package/dist/renderables/markdown.d.ts +1 -1
- package/dist/renderables/markdown.js +6 -4
- package/dist/renderables/padding.js +3 -2
- package/dist/renderables/panel.js +26 -41
- package/dist/renderables/progress.js +5 -8
- package/dist/renderables/progressBar.js +6 -5
- package/dist/renderables/rule.d.ts +3 -2
- package/dist/renderables/rule.js +9 -9
- package/dist/renderables/spinner.d.ts +5 -3
- package/dist/renderables/spinner.js +14 -8
- package/dist/renderables/syntax.d.ts +1 -1
- package/dist/renderables/syntax.js +2 -1
- package/dist/renderables/table.d.ts +26 -14
- package/dist/renderables/table.js +239 -141
- package/dist/renderables/traceback.js +8 -9
- package/dist/renderables/tree.d.ts +17 -3
- package/dist/renderables/tree.js +62 -71
- package/dist/renderables/viewport.d.ts +114 -0
- package/dist/renderables/viewport.js +198 -0
- package/dist/template-bindings/color-funcs.js +11 -13
- package/dist/template-bindings/index.js +4 -2
- package/dist/template-bindings/palette-funcs.js +6 -16
- package/dist/template-bindings/style-funcs.js +4 -0
- package/dist/themes/data/ansi-tables.d.ts +14 -0
- package/dist/themes/data/ansi-tables.js +49 -0
- package/dist/themes/data/atom-one-dark.js +19 -0
- package/dist/themes/data/atom-one-light.js +19 -0
- package/dist/themes/data/catppuccin-frappe.js +19 -0
- package/dist/themes/data/catppuccin-latte.js +19 -0
- package/dist/themes/data/catppuccin-macchiato.js +19 -0
- package/dist/themes/data/catppuccin-mocha.js +19 -0
- package/dist/themes/data/cyberpunk.js +2 -0
- package/dist/themes/data/default.js +2 -0
- package/dist/themes/data/dracula.js +19 -0
- package/dist/themes/data/flexoki.js +19 -0
- package/dist/themes/data/gruvbox.js +19 -0
- package/dist/themes/data/monokai.js +19 -0
- package/dist/themes/data/nord.js +19 -0
- package/dist/themes/data/rose-pine-dawn.js +19 -0
- package/dist/themes/data/rose-pine-moon.js +19 -0
- package/dist/themes/data/rose-pine.js +19 -0
- package/dist/themes/data/solarized-dark.js +19 -0
- package/dist/themes/data/solarized-light.js +19 -0
- package/dist/themes/data/svg-export.js +19 -0
- package/dist/themes/data/textual-ansi.js +2 -0
- package/dist/themes/data/textual-dark.js +2 -0
- package/dist/themes/data/textual-light.js +2 -0
- package/dist/themes/data/tokyo-night.js +19 -0
- package/dist/themes/data/types.d.ts +16 -0
- package/dist/themes/data/types.js +10 -1
- package/dist/themes/registry.d.ts +3 -2
- package/dist/themes/registry.js +13 -1
- package/dist/themes/terminalThemes.d.ts +2 -7
- package/dist/themes/terminalThemes.js +4 -9
- package/dist/widgets/button.d.ts +1 -1
- package/dist/widgets/button.js +4 -2
- package/dist/widgets/checkbox.d.ts +2 -2
- package/dist/widgets/checkbox.js +5 -3
- package/dist/widgets/dropdown.d.ts +2 -2
- package/dist/widgets/dropdown.js +13 -16
- package/dist/widgets/event-router.d.ts +21 -28
- package/dist/widgets/event-router.js +80 -73
- package/dist/widgets/focus-manager.d.ts +25 -6
- package/dist/widgets/focus-manager.js +63 -65
- package/dist/widgets/hit.d.ts +64 -0
- package/dist/widgets/hit.js +113 -0
- package/dist/widgets/index.d.ts +5 -7
- package/dist/widgets/index.js +3 -4
- package/dist/widgets/slider.d.ts +2 -2
- package/dist/widgets/slider.js +7 -7
- package/dist/widgets/static-item.d.ts +9 -15
- package/dist/widgets/static-item.js +9 -15
- package/dist/widgets/text-input.d.ts +2 -2
- package/dist/widgets/text-input.js +17 -14
- package/dist/widgets/toggle.d.ts +1 -1
- package/dist/widgets/toggle.js +3 -2
- package/dist/widgets/types.d.ts +14 -35
- package/dist/widgets/types.js +0 -1
- package/dist/widgets/widget-app.d.ts +63 -0
- package/dist/widgets/widget-app.js +199 -0
- package/dist/widgets/widget-base.d.ts +4 -6
- package/dist/widgets/widget-base.js +22 -30
- package/package.json +12 -4
- package/dist/host/host-stream.d.ts +0 -30
- package/dist/host/host-stream.js +0 -35
- package/dist/widgets/screen.d.ts +0 -98
- package/dist/widgets/screen.js +0 -530
package/dist/core/strip.js
CHANGED
|
@@ -29,6 +29,7 @@ import { Segment } from "./segment.js";
|
|
|
29
29
|
import { Style } from "./style.js";
|
|
30
30
|
import { ColorDepth, ColorSpec, blendRgb } from "./color.js";
|
|
31
31
|
import { Oklch } from "./oklch.js";
|
|
32
|
+
import { drawable } from "./protocol.js";
|
|
32
33
|
// --- Strip ---
|
|
33
34
|
export class Strip {
|
|
34
35
|
items;
|
|
@@ -72,17 +73,6 @@ const EMPTY = {
|
|
|
72
73
|
// intentionally empty
|
|
73
74
|
},
|
|
74
75
|
};
|
|
75
|
-
class FixedSegment {
|
|
76
|
-
_text;
|
|
77
|
-
_style;
|
|
78
|
-
constructor(text, style) {
|
|
79
|
-
this._text = text;
|
|
80
|
-
this._style = style;
|
|
81
|
-
}
|
|
82
|
-
*render(_options) {
|
|
83
|
-
yield new Segment(this._text, this._style);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
76
|
/** A renderable whose segments are computed from the options it is rendered with. */
|
|
87
77
|
function deferred(emit) {
|
|
88
78
|
return { render: emit };
|
|
@@ -159,16 +149,18 @@ export const POWERLINE_JOINER_GLYPHS = Object.freeze({
|
|
|
159
149
|
lead: "\ue0d7",
|
|
160
150
|
tail: "\ue0b0",
|
|
161
151
|
});
|
|
152
|
+
/** The powerline set in ASCII: an arrow for every join, runs begun flat. */
|
|
153
|
+
const ASCII_POWERLINE_GLYPHS = Object.freeze({
|
|
154
|
+
glyph: ">",
|
|
155
|
+
divider: ">",
|
|
156
|
+
lead: "",
|
|
157
|
+
tail: ">",
|
|
158
|
+
});
|
|
159
|
+
const powerlineGlyphs = ({ glyph, divider, lead, tail }) => glyph + divider + lead + tail;
|
|
162
160
|
export class PowerlineJoiner {
|
|
163
|
-
|
|
164
|
-
_divider;
|
|
165
|
-
_lead;
|
|
166
|
-
_tail;
|
|
161
|
+
_glyphs;
|
|
167
162
|
constructor(options = POWERLINE_JOINER_GLYPHS) {
|
|
168
|
-
this.
|
|
169
|
-
this._divider = options.divider;
|
|
170
|
-
this._lead = options.lead;
|
|
171
|
-
this._tail = options.tail;
|
|
163
|
+
this._glyphs = options;
|
|
172
164
|
}
|
|
173
165
|
join(left, right) {
|
|
174
166
|
// [LAW:dataflow-not-control-flow] One table for all three positions (start
|
|
@@ -196,11 +188,9 @@ export class PowerlineJoiner {
|
|
|
196
188
|
// is the only thing that elides the separator, and that is paint logic.
|
|
197
189
|
// "Absent" = no bg OR the terminal default (transparent) — paintableBg folds
|
|
198
190
|
// both to undefined so an explicit `… on default` cannot smuggle a separator.
|
|
199
|
-
const
|
|
200
|
-
const divider = this._divider;
|
|
201
|
-
const lead = this._lead;
|
|
202
|
-
const tail = this._tail;
|
|
191
|
+
const glyphs = this._glyphs;
|
|
203
192
|
return deferred(function* (options) {
|
|
193
|
+
const { glyph, divider, lead, tail } = drawable(options, glyphs, ASCII_POWERLINE_GLYPHS, powerlineGlyphs);
|
|
204
194
|
const leftEdge = left?.edgeStyle("right", options);
|
|
205
195
|
const leftBg = paintableBg(leftEdge?.bgcolor);
|
|
206
196
|
const rightBg = paintableBg(right?.edgeStyle("left", options).bgcolor);
|
|
@@ -222,31 +212,33 @@ export class PowerlineJoiner {
|
|
|
222
212
|
});
|
|
223
213
|
}
|
|
224
214
|
}
|
|
215
|
+
const ASCII_CAPS = { left: "(", right: ")" };
|
|
216
|
+
const capGlyphs = ({ left, right }) => left + right;
|
|
225
217
|
export class CapsuleJoiner {
|
|
226
|
-
|
|
227
|
-
_right;
|
|
218
|
+
_caps;
|
|
228
219
|
_separator;
|
|
229
220
|
constructor(options) {
|
|
230
|
-
this.
|
|
231
|
-
this._right = options?.right ?? "";
|
|
221
|
+
this._caps = { left: options?.left ?? "", right: options?.right ?? "" };
|
|
232
222
|
this._separator = options?.separator ?? " ";
|
|
233
223
|
}
|
|
234
224
|
*_emit(left, right, options) {
|
|
225
|
+
const caps = drawable(options, this._caps, ASCII_CAPS, capGlyphs);
|
|
226
|
+
const separator = drawable(options, this._separator, " ");
|
|
235
227
|
if (left === null && right === null)
|
|
236
228
|
return;
|
|
237
229
|
if (left === null) {
|
|
238
|
-
yield new Segment(
|
|
230
|
+
yield new Segment(caps.left, bgAsFg(right.edgeStyle("left", options)));
|
|
239
231
|
return;
|
|
240
232
|
}
|
|
241
233
|
if (right === null) {
|
|
242
|
-
yield new Segment(
|
|
234
|
+
yield new Segment(caps.right, bgAsFg(left.edgeStyle("right", options)));
|
|
243
235
|
return;
|
|
244
236
|
}
|
|
245
237
|
// Middle: close the left capsule, separator (unstyled), open the right.
|
|
246
|
-
yield new Segment(
|
|
247
|
-
if (
|
|
248
|
-
yield new Segment(
|
|
249
|
-
yield new Segment(
|
|
238
|
+
yield new Segment(caps.right, bgAsFg(left.edgeStyle("right", options)));
|
|
239
|
+
if (separator.length > 0)
|
|
240
|
+
yield new Segment(separator);
|
|
241
|
+
yield new Segment(caps.left, bgAsFg(right.edgeStyle("left", options)));
|
|
250
242
|
}
|
|
251
243
|
join(left, right) {
|
|
252
244
|
return deferred((options) => this._emit(left, right, options));
|
|
@@ -263,7 +255,9 @@ export class PlainJoiner {
|
|
|
263
255
|
// Endpoints are empty — a fixed separator has no natural cap.
|
|
264
256
|
if (left === null || right === null)
|
|
265
257
|
return EMPTY;
|
|
266
|
-
|
|
258
|
+
const separator = this._separator;
|
|
259
|
+
const style = this._style;
|
|
260
|
+
return deferred((options) => [new Segment(drawable(options, separator, " | "), style)]);
|
|
267
261
|
}
|
|
268
262
|
}
|
|
269
263
|
/**
|
|
@@ -292,6 +286,9 @@ export class GradientJoiner {
|
|
|
292
286
|
return;
|
|
293
287
|
const lTrip = lbg.getTruecolor();
|
|
294
288
|
const rTrip = rbg.getTruecolor();
|
|
289
|
+
// An ASCII cell carries one sample, the background: the gradient keeps
|
|
290
|
+
// its colours at half the resolution.
|
|
291
|
+
const half = drawable(options, HALF_BLOCK, " ");
|
|
295
292
|
const samples = 2 * steps;
|
|
296
293
|
// Midpoint sampling across `2 * steps` half-cell positions: sample j has
|
|
297
294
|
// t = (j + 0.5) / samples. Cell i takes samples 2i (left half) and 2i+1
|
|
@@ -301,7 +298,7 @@ export class GradientJoiner {
|
|
|
301
298
|
const tRight = (2 * i + 1.5) / samples;
|
|
302
299
|
const fg = ColorSpec.fromRgba(blendRgb(lTrip, rTrip, tLeft));
|
|
303
300
|
const bg = ColorSpec.fromRgba(blendRgb(lTrip, rTrip, tRight));
|
|
304
|
-
yield new Segment(
|
|
301
|
+
yield new Segment(half, new Style({ color: fg, bgcolor: bg }));
|
|
305
302
|
}
|
|
306
303
|
});
|
|
307
304
|
}
|
package/dist/core/style.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Immutable style descriptors — colors, text attributes, links, metadata.
|
|
3
3
|
*/
|
|
4
4
|
import { ColorSpec, ColorDepth } from "./color.js";
|
|
5
|
+
import { type Anchor } from "./anchor.js";
|
|
5
6
|
/**
|
|
6
7
|
* Canonical text-attribute inventory. Single source of truth consumed by
|
|
7
8
|
* `Style.parse` / `Style.toString` and the template bindings — adding an
|
|
@@ -10,6 +11,7 @@ import { ColorSpec, ColorDepth } from "./color.js";
|
|
|
10
11
|
*/
|
|
11
12
|
export declare const ATTRIBUTE_NAMES: readonly ["bold", "dim", "italic", "underline", "blink", "blink2", "reverse", "conceal", "strike", "underline2", "frame", "encircle", "overline"];
|
|
12
13
|
export type AttributeName = (typeof ATTRIBUTE_NAMES)[number];
|
|
14
|
+
export declare const ATTRIBUTE_SGR: Record<AttributeName, number>;
|
|
13
15
|
/**
|
|
14
16
|
* Canonical short-attribute aliases (`b` → `bold`, `i` → `italic`, …).
|
|
15
17
|
* Single source of truth consumed by `Style.parse` and the template
|
|
@@ -35,6 +37,7 @@ export interface StyleOptions {
|
|
|
35
37
|
overline?: boolean;
|
|
36
38
|
link?: string;
|
|
37
39
|
meta?: Record<string, unknown>;
|
|
40
|
+
anchor?: Anchor;
|
|
38
41
|
}
|
|
39
42
|
export declare class StyleSyntaxError extends Error {
|
|
40
43
|
constructor(message: string, options?: ErrorOptions);
|
|
@@ -57,13 +60,35 @@ export declare class Style {
|
|
|
57
60
|
readonly overline: boolean | undefined;
|
|
58
61
|
readonly link: string | undefined;
|
|
59
62
|
readonly meta: Record<string, unknown> | undefined;
|
|
63
|
+
/**
|
|
64
|
+
* Where this style's cells sat in the output of whatever drew them; see
|
|
65
|
+
* `./anchor.ts`. It draws nothing, and it makes two styles that draw alike
|
|
66
|
+
* unequal, because they came from different places.
|
|
67
|
+
*/
|
|
68
|
+
readonly anchor: Anchor | undefined;
|
|
60
69
|
constructor(options?: StyleOptions);
|
|
61
70
|
get isNull(): boolean;
|
|
62
71
|
get transparentBackground(): boolean;
|
|
63
72
|
get backgroundStyle(): Style;
|
|
73
|
+
/**
|
|
74
|
+
* This style with `overrides` in place of its own fields.
|
|
75
|
+
*
|
|
76
|
+
* [LAW:one-source-of-truth] The field list is the class's own fields, so a
|
|
77
|
+
* field added to `Style` is carried by every copy without being named here.
|
|
78
|
+
*/
|
|
79
|
+
private with;
|
|
64
80
|
get withoutColor(): Style;
|
|
65
81
|
withLink(link: string | undefined): Style;
|
|
66
82
|
clearMetaAndLinks(): Style;
|
|
83
|
+
/**
|
|
84
|
+
* The same look, drawn from the place `anchor` names, or from nowhere.
|
|
85
|
+
*/
|
|
86
|
+
withAnchor(anchor: Anchor | undefined): Style;
|
|
87
|
+
/**
|
|
88
|
+
* This style on the cell `cells` to the right: its anchor shifted along its
|
|
89
|
+
* row, or the style itself when it has no anchor.
|
|
90
|
+
*/
|
|
91
|
+
shiftedBy(cells: number): Style;
|
|
67
92
|
/**
|
|
68
93
|
* Merges two styles. `other`'s values take priority.
|
|
69
94
|
*/
|
package/dist/core/style.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Immutable style descriptors — colors, text attributes, links, metadata.
|
|
3
3
|
*/
|
|
4
4
|
import { COLOR_NAMES, ColorSpec, SURFACE_BLACK, } from "./color.js";
|
|
5
|
+
import { shiftAnchor } from "./anchor.js";
|
|
5
6
|
// [LAW:one-way-deps] `core/style` depends only on `core/color`. The substrate
|
|
6
7
|
// a translucent colour is flattened over is `SURFACE_BLACK`, defined beside
|
|
7
8
|
// `compositeOver`.
|
|
@@ -27,8 +28,8 @@ export const ATTRIBUTE_NAMES = [
|
|
|
27
28
|
"encircle",
|
|
28
29
|
"overline",
|
|
29
30
|
];
|
|
30
|
-
// The SGR parameter that turns each attribute on
|
|
31
|
-
const ATTRIBUTE_SGR = {
|
|
31
|
+
// The SGR parameter that turns each attribute on. `ansi.ts` reads it back.
|
|
32
|
+
export const ATTRIBUTE_SGR = {
|
|
32
33
|
bold: 1,
|
|
33
34
|
dim: 2,
|
|
34
35
|
italic: 3,
|
|
@@ -86,27 +87,13 @@ export class Style {
|
|
|
86
87
|
overline;
|
|
87
88
|
link;
|
|
88
89
|
meta;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
this.underline = undefined;
|
|
97
|
-
this.blink = undefined;
|
|
98
|
-
this.blink2 = undefined;
|
|
99
|
-
this.reverse = undefined;
|
|
100
|
-
this.conceal = undefined;
|
|
101
|
-
this.strike = undefined;
|
|
102
|
-
this.underline2 = undefined;
|
|
103
|
-
this.frame = undefined;
|
|
104
|
-
this.encircle = undefined;
|
|
105
|
-
this.overline = undefined;
|
|
106
|
-
this.link = undefined;
|
|
107
|
-
this.meta = undefined;
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
90
|
+
/**
|
|
91
|
+
* Where this style's cells sat in the output of whatever drew them; see
|
|
92
|
+
* `./anchor.ts`. It draws nothing, and it makes two styles that draw alike
|
|
93
|
+
* unequal, because they came from different places.
|
|
94
|
+
*/
|
|
95
|
+
anchor;
|
|
96
|
+
constructor(options = {}) {
|
|
110
97
|
this.color = resolveColor(options.color);
|
|
111
98
|
this.bgcolor = resolveColor(options.bgcolor);
|
|
112
99
|
this.bold = options.bold;
|
|
@@ -124,6 +111,7 @@ export class Style {
|
|
|
124
111
|
this.overline = options.overline;
|
|
125
112
|
this.link = options.link;
|
|
126
113
|
this.meta = options.meta;
|
|
114
|
+
this.anchor = options.anchor;
|
|
127
115
|
}
|
|
128
116
|
get isNull() {
|
|
129
117
|
return (this.color === undefined &&
|
|
@@ -142,7 +130,8 @@ export class Style {
|
|
|
142
130
|
this.encircle === undefined &&
|
|
143
131
|
this.overline === undefined &&
|
|
144
132
|
this.link === undefined &&
|
|
145
|
-
this.meta === undefined
|
|
133
|
+
this.meta === undefined &&
|
|
134
|
+
this.anchor === undefined);
|
|
146
135
|
}
|
|
147
136
|
get transparentBackground() {
|
|
148
137
|
return this.bgcolor === undefined || this.bgcolor.isDefault;
|
|
@@ -150,68 +139,40 @@ export class Style {
|
|
|
150
139
|
get backgroundStyle() {
|
|
151
140
|
return new Style({ bgcolor: this.bgcolor });
|
|
152
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* This style with `overrides` in place of its own fields.
|
|
144
|
+
*
|
|
145
|
+
* [LAW:one-source-of-truth] The field list is the class's own fields, so a
|
|
146
|
+
* field added to `Style` is carried by every copy without being named here.
|
|
147
|
+
*/
|
|
148
|
+
with(overrides) {
|
|
149
|
+
return new Style({ ...this, ...overrides });
|
|
150
|
+
}
|
|
153
151
|
get withoutColor() {
|
|
154
|
-
return
|
|
155
|
-
bold: this.bold,
|
|
156
|
-
dim: this.dim,
|
|
157
|
-
italic: this.italic,
|
|
158
|
-
underline: this.underline,
|
|
159
|
-
blink: this.blink,
|
|
160
|
-
blink2: this.blink2,
|
|
161
|
-
reverse: this.reverse,
|
|
162
|
-
conceal: this.conceal,
|
|
163
|
-
strike: this.strike,
|
|
164
|
-
underline2: this.underline2,
|
|
165
|
-
frame: this.frame,
|
|
166
|
-
encircle: this.encircle,
|
|
167
|
-
overline: this.overline,
|
|
168
|
-
link: this.link,
|
|
169
|
-
meta: this.meta,
|
|
170
|
-
});
|
|
152
|
+
return this.with({ color: undefined, bgcolor: undefined });
|
|
171
153
|
}
|
|
172
154
|
// [LAW:types-are-the-program] Structural clone helper — pure rearrangement
|
|
173
155
|
// of fields, no policy. Sanitization of the URL is the trust boundary's
|
|
174
156
|
// job (see RichText in text.ts); Style stays a faithful container so
|
|
175
157
|
// callers that have already sanitized are not silently re-mutated.
|
|
176
158
|
withLink(link) {
|
|
177
|
-
return
|
|
178
|
-
color: this.color,
|
|
179
|
-
bgcolor: this.bgcolor,
|
|
180
|
-
bold: this.bold,
|
|
181
|
-
dim: this.dim,
|
|
182
|
-
italic: this.italic,
|
|
183
|
-
underline: this.underline,
|
|
184
|
-
blink: this.blink,
|
|
185
|
-
blink2: this.blink2,
|
|
186
|
-
reverse: this.reverse,
|
|
187
|
-
conceal: this.conceal,
|
|
188
|
-
strike: this.strike,
|
|
189
|
-
underline2: this.underline2,
|
|
190
|
-
frame: this.frame,
|
|
191
|
-
encircle: this.encircle,
|
|
192
|
-
overline: this.overline,
|
|
193
|
-
link,
|
|
194
|
-
meta: this.meta,
|
|
195
|
-
});
|
|
159
|
+
return this.with({ link });
|
|
196
160
|
}
|
|
197
161
|
clearMetaAndLinks() {
|
|
198
|
-
return
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
encircle: this.encircle,
|
|
213
|
-
overline: this.overline,
|
|
214
|
-
});
|
|
162
|
+
return this.with({ link: undefined, meta: undefined });
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The same look, drawn from the place `anchor` names, or from nowhere.
|
|
166
|
+
*/
|
|
167
|
+
withAnchor(anchor) {
|
|
168
|
+
return this.with({ anchor });
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* This style on the cell `cells` to the right: its anchor shifted along its
|
|
172
|
+
* row, or the style itself when it has no anchor.
|
|
173
|
+
*/
|
|
174
|
+
shiftedBy(cells) {
|
|
175
|
+
return this.anchor ? this.withAnchor(shiftAnchor(this.anchor, cells)) : this;
|
|
215
176
|
}
|
|
216
177
|
/**
|
|
217
178
|
* Merges two styles. `other`'s values take priority.
|
|
@@ -241,6 +202,7 @@ export class Style {
|
|
|
241
202
|
meta: other.meta && this.meta
|
|
242
203
|
? { ...this.meta, ...other.meta }
|
|
243
204
|
: other.meta ?? this.meta,
|
|
205
|
+
anchor: other.anchor ?? this.anchor,
|
|
244
206
|
});
|
|
245
207
|
}
|
|
246
208
|
equals(other) {
|
|
@@ -261,7 +223,8 @@ export class Style {
|
|
|
261
223
|
this.frame === other.frame &&
|
|
262
224
|
this.encircle === other.encircle &&
|
|
263
225
|
this.overline === other.overline &&
|
|
264
|
-
this.link === other.link
|
|
226
|
+
this.link === other.link &&
|
|
227
|
+
anchorsEqual(this.anchor, other.anchor));
|
|
265
228
|
}
|
|
266
229
|
/**
|
|
267
230
|
* The colours this style puts on screen at `colorSystem`: each flattened
|
|
@@ -297,18 +260,17 @@ export class Style {
|
|
|
297
260
|
toSgrCodes(colorSystem) {
|
|
298
261
|
if (this.isNull)
|
|
299
262
|
return "";
|
|
300
|
-
|
|
263
|
+
// Attributes, then foreground, then background: Python Rich 9d8f9a3's
|
|
264
|
+
// `_make_ansi_codes` order, so a byte pinned against the reference holds.
|
|
265
|
+
// An attribute set false writes nothing, as there. It overrides an
|
|
266
|
+
// inherited attribute when styles combine, and every styled run is written
|
|
267
|
+
// after a reset, so no off code is ever needed.
|
|
301
268
|
const drawn = this.drawnColors(colorSystem);
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
// `_make_ansi_codes`. It overrides an inherited attribute when styles
|
|
308
|
-
// combine, and every styled run is written after a reset, so no off
|
|
309
|
-
// code is ever needed.
|
|
310
|
-
attrs.push(...ATTRIBUTE_NAMES.filter((name) => this[name] === true).map((name) => `${ATTRIBUTE_SGR[name]}`));
|
|
311
|
-
return attrs.join(";");
|
|
269
|
+
return [
|
|
270
|
+
...ATTRIBUTE_NAMES.filter((name) => this[name] === true).map((name) => `${ATTRIBUTE_SGR[name]}`),
|
|
271
|
+
...(drawn.color?.getAnsiCodes(true) ?? []),
|
|
272
|
+
...(drawn.bgcolor?.getAnsiCodes(false) ?? []),
|
|
273
|
+
].join(";");
|
|
312
274
|
}
|
|
313
275
|
/**
|
|
314
276
|
* Serializes to a canonical string that round-trips through `Style.parse()`.
|
|
@@ -680,6 +642,9 @@ export const DEFAULT_STYLES = {
|
|
|
680
642
|
"bar.complete": Style.parse("magenta"),
|
|
681
643
|
"bar.finished": Style.parse("green"),
|
|
682
644
|
"bar.pulse": Style.parse("magenta"),
|
|
645
|
+
// Scrollbar
|
|
646
|
+
"scrollbar.thumb": NULL_STYLE,
|
|
647
|
+
"scrollbar.track": Style.parse("grey37"),
|
|
683
648
|
// Tree
|
|
684
649
|
"tree": NULL_STYLE,
|
|
685
650
|
"tree.guide": NULL_STYLE,
|
|
@@ -721,3 +686,10 @@ export const DEFAULT_STYLES = {
|
|
|
721
686
|
* a renderable sees outside a `Console`, as in `renderToString`.
|
|
722
687
|
*/
|
|
723
688
|
export const DEFAULT_THEME = new Theme();
|
|
689
|
+
function anchorsEqual(a, b) {
|
|
690
|
+
if (a === b)
|
|
691
|
+
return true;
|
|
692
|
+
if (!a || !b)
|
|
693
|
+
return false;
|
|
694
|
+
return a.owner === b.owner && a.row === b.row && a.col === b.col && anchorsEqual(a.inner, b.inner);
|
|
695
|
+
}
|
package/dist/core/text.d.ts
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { Segment } from "./segment.js";
|
|
5
5
|
import { Style } from "./style.js";
|
|
6
|
-
import type { Renderable, Measurable, RenderOptions } from "./protocol.js";
|
|
6
|
+
import type { Renderable, Measurable, OverflowMethod, RenderOptions } from "./protocol.js";
|
|
7
|
+
export declare function stripControlChars(text: string): string;
|
|
7
8
|
export declare class Span {
|
|
8
9
|
readonly start: number;
|
|
9
10
|
readonly end: number;
|
|
@@ -19,7 +20,7 @@ export declare class Span {
|
|
|
19
20
|
export interface RichTextOptions {
|
|
20
21
|
style?: string | Style;
|
|
21
22
|
justify?: "left" | "center" | "right" | "full";
|
|
22
|
-
overflow?:
|
|
23
|
+
overflow?: OverflowMethod;
|
|
23
24
|
end?: string;
|
|
24
25
|
tabSize?: number;
|
|
25
26
|
noWrap?: boolean;
|
|
@@ -44,8 +45,8 @@ export declare class RichText implements Renderable, Measurable {
|
|
|
44
45
|
set style(value: string | Style);
|
|
45
46
|
get justify(): "left" | "center" | "right" | "full" | undefined;
|
|
46
47
|
set justify(value: "left" | "center" | "right" | "full" | undefined);
|
|
47
|
-
get overflow():
|
|
48
|
-
set overflow(value:
|
|
48
|
+
get overflow(): OverflowMethod | undefined;
|
|
49
|
+
set overflow(value: OverflowMethod | undefined);
|
|
49
50
|
get end(): string;
|
|
50
51
|
set end(value: string);
|
|
51
52
|
get noWrap(): boolean;
|
|
@@ -114,7 +115,10 @@ export declare class RichText implements Renderable, Measurable {
|
|
|
114
115
|
* in the middle.
|
|
115
116
|
*
|
|
116
117
|
* Marker default is `"\u2026"`. Pass `marker: ""` for raw cropping without an
|
|
117
|
-
* indicator glyph.
|
|
118
|
+
* indicator glyph. A marker wider than `width` is itself cut to the glyphs
|
|
119
|
+
* that fit, and the text takes whatever cells that leaves — all of them, when
|
|
120
|
+
* not one glyph of the marker fits — so the result is never wider than asked.
|
|
121
|
+
* Every cut, marker and text alike, falls between grapheme clusters.
|
|
118
122
|
*
|
|
119
123
|
* Spans are preserved through the cut: characters that survive keep their
|
|
120
124
|
* styling; the marker (if any) is inserted as plain text with no span.
|
|
@@ -130,10 +134,6 @@ export declare class RichText implements Renderable, Measurable {
|
|
|
130
134
|
}): this;
|
|
131
135
|
private _cropRightTo;
|
|
132
136
|
private _cropLeftTo;
|
|
133
|
-
/** Number of char-index code units that fit within `targetWidth` cell columns from the left. */
|
|
134
|
-
private _cellPrefixCharLength;
|
|
135
|
-
/** Char-index at which the suffix of `targetWidth` cell columns starts. */
|
|
136
|
-
private _cellSuffixStartCharIndex;
|
|
137
137
|
align(justify: "left" | "center" | "right", width: number): this;
|
|
138
138
|
removeSuffix(suffix: string): this;
|
|
139
139
|
appendTokens(tokens: Array<[string, (string | Style)?]>): this;
|
|
@@ -150,9 +150,8 @@ export declare class RichText implements Renderable, Measurable {
|
|
|
150
150
|
* `{{ red "x" }}{{ blue "y" }}` evaluates to two fragments — one with
|
|
151
151
|
* wrapping `style = red`, one with `blue` — and consumers that want a
|
|
152
152
|
* single styled string for downstream rendering need both styles
|
|
153
|
-
* preserved as spans on the concatenated result
|
|
154
|
-
*
|
|
155
|
-
* lifting `frag.style` into a span before appending.
|
|
153
|
+
* preserved as spans on the concatenated result, which is what `append()`
|
|
154
|
+
* does with each fragment.
|
|
156
155
|
*
|
|
157
156
|
* Empty input → empty `RichText` with `end: ""`. Caller can override
|
|
158
157
|
* `end` (defaults to `""` — the engine-output case rarely wants a
|
|
@@ -247,9 +246,11 @@ export declare class RichText implements Renderable, Measurable {
|
|
|
247
246
|
*
|
|
248
247
|
* Everything reaching here already survived wrapping, so the only text still
|
|
249
248
|
* too wide is text no break could help: a word longer than the canvas under
|
|
250
|
-
* a non-folding overflow method, a glyph wider than the budget,
|
|
251
|
-
* with no cells at all
|
|
252
|
-
*
|
|
249
|
+
* a non-folding overflow method, a glyph wider than the budget, a canvas
|
|
250
|
+
* with no cells at all, or a `noWrap` line, which no break was allowed to
|
|
251
|
+
* help. That is what makes the overflow method a last resort rather than the
|
|
252
|
+
* first thing a long cell meets. `"fold"` has nothing left to fold here and
|
|
253
|
+
* cuts as `"crop"` does, as the reference's `truncate` does.
|
|
253
254
|
*/
|
|
254
255
|
private _fitLine;
|
|
255
256
|
}
|