@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
|
@@ -20,7 +20,7 @@ const HALF_BAR_LEFT = "╺";
|
|
|
20
20
|
*/
|
|
21
21
|
const PULSE_CURVE = { ...EFFECT_CURVES.shimmer, seconds: 5 };
|
|
22
22
|
const PULSE_REACH = 10;
|
|
23
|
-
/** Rich's pulse back where the back style names no
|
|
23
|
+
/** Rich's pulse back where the back style names no color. */
|
|
24
24
|
const PULSE_BACK = ColorSpec.fromRgba(new ColorRgba(0, 0, 0));
|
|
25
25
|
export class ProgressBar {
|
|
26
26
|
// Rich's ProgressBar is updated after it is built: `bar.completed = n`.
|
|
@@ -70,31 +70,34 @@ export class ProgressBar {
|
|
|
70
70
|
return;
|
|
71
71
|
}
|
|
72
72
|
const depth = options.colorSystem ?? ColorDepth.TRUECOLOR;
|
|
73
|
-
// Rich's pulse resolves its
|
|
74
|
-
// `get_truecolor` does with no theme; so does this.
|
|
75
|
-
const
|
|
76
|
-
// Rich writes the pulse's back as a
|
|
77
|
-
// back style names none, so the light always has the bar's
|
|
73
|
+
// Rich's pulse resolves its colors on the terminal a depth assumes, as
|
|
74
|
+
// `get_truecolor` does with no theme; so does this with none named.
|
|
75
|
+
const terminal = resolveTerminal(options.terminal, depth);
|
|
76
|
+
// Rich writes the pulse's back as a color of its own, black where the
|
|
77
|
+
// back style names none, so the light always has the bar's color to fall
|
|
78
78
|
// on: one the terminal supplies takes no light.
|
|
79
79
|
const style = getStyle(options, this.style);
|
|
80
|
-
const ink = style.color?.isDefault === false ? style.color : ColorSpec.fromRgba((style.color ?? PULSE_BACK).getTruecolor(
|
|
80
|
+
const ink = style.color?.isDefault === false ? style.color : ColorSpec.fromRgba((style.color ?? PULSE_BACK).getTruecolor(terminal, true));
|
|
81
81
|
const back = style.add(Style.fromColor(ink));
|
|
82
82
|
// [LAW:no-ambient-temporal-coupling] The moment is the frame's; the bar
|
|
83
83
|
// only says what it looks like then. An empty track, lit by the shimmer.
|
|
84
84
|
const track = { render: (o) => this.track(o, width, 0, back) };
|
|
85
|
-
yield* render(new Effected(track, this.pulseEffect(options, back
|
|
85
|
+
yield* render(new Effected(track, this.pulseEffect(options, back), { key: "progress-bar" }), options);
|
|
86
86
|
}
|
|
87
87
|
/**
|
|
88
|
-
* The shimmer over this bar's back
|
|
89
|
-
*
|
|
90
|
-
*
|
|
88
|
+
* The shimmer over this bar's back color as `Effected` sees it drawn,
|
|
89
|
+
* toward `bar.pulse`. A bar has no words to keep legible, so its back takes
|
|
90
|
+
* the whole of the light.
|
|
91
91
|
*/
|
|
92
|
-
pulseEffect(options, back
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
pulseEffect(options, back) {
|
|
93
|
+
return (drawn) => {
|
|
94
|
+
const { depth, terminal } = drawn;
|
|
95
|
+
const ink = back.drawnColors(depth).color ?? ColorSpec.default();
|
|
96
|
+
const glow = getStyle(options, "bar.pulse").drawnColors(depth).color ?? ColorSpec.default();
|
|
97
|
+
const loop = shimmer(PULSE_CURVE, PULSE_REACH, glow.getTruecolor(terminal, true), 0);
|
|
98
|
+
const whole = new Map([[ink.getTruecolor(terminal, true).hex, 1]]);
|
|
99
|
+
return atShares(loop, () => whole)(drawn);
|
|
100
|
+
};
|
|
98
101
|
}
|
|
99
102
|
/** Rich 9d8f9a3 `__rich_console__`: the fill is counted in half cells, and a total of zero is a bar already full. */
|
|
100
103
|
completeHalves(width) {
|
|
@@ -114,7 +117,7 @@ export class ProgressBar {
|
|
|
114
117
|
yield new Segment(bar.repeat(barCount), fillStyle);
|
|
115
118
|
if (halfBarCount)
|
|
116
119
|
yield new Segment(drawable(options, HALF_BAR_RIGHT, " "), fillStyle);
|
|
117
|
-
// The back is drawn in
|
|
120
|
+
// The back is drawn in color alone, so an output with none leaves it blank.
|
|
118
121
|
if (options.colorSystem === null)
|
|
119
122
|
return;
|
|
120
123
|
let remaining = width - barCount - halfBarCount;
|
|
@@ -29,7 +29,7 @@ import { RichText } from "../core/text.js";
|
|
|
29
29
|
* on, and resolves with the raw user response. Implementations decide where
|
|
30
30
|
* the input comes from (stdin readline, network, in-memory queue, etc.); the
|
|
31
31
|
* console is what the prompt is drawn with, as Rich's `Console.input` draws
|
|
32
|
-
* it — its theme, its
|
|
32
|
+
* it — its theme, its colors, the target it writes to.
|
|
33
33
|
*
|
|
34
34
|
* [LAW:effects-at-boundaries] The prompt arrives as a `RichText`, not bytes:
|
|
35
35
|
* encoding it is the console's job, and the console arrives with it.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* [LAW:one-type-per-behavior] A marquee, a scroll and a slide are one window
|
|
7
7
|
* and differ only in the motion handed in: the offset along each axis is an
|
|
8
|
-
* `Animation<number>`, so a marquee is a looping `
|
|
8
|
+
* `Animation<number>`, so a marquee is a looping `WrapMode` scaled to the span
|
|
9
9
|
* it crosses and a slide-in is a `tween` to 0, and when the window next
|
|
10
10
|
* changes is `Animation.all`'s answer over the two. Nothing here knows which
|
|
11
11
|
* one it is drawing.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* [LAW:one-type-per-behavior] A marquee, a scroll and a slide are one window
|
|
7
7
|
* and differ only in the motion handed in: the offset along each axis is an
|
|
8
|
-
* `Animation<number>`, so a marquee is a looping `
|
|
8
|
+
* `Animation<number>`, so a marquee is a looping `WrapMode` scaled to the span
|
|
9
9
|
* it crosses and a slide-in is a `tween` to 0, and when the window next
|
|
10
10
|
* changes is `Animation.all`'s answer over the two. Nothing here knows which
|
|
11
11
|
* one it is drawing.
|
|
@@ -91,8 +91,8 @@ class ScrollFrame {
|
|
|
91
91
|
// [LAW:one-source-of-truth] What the window shows is cut from the whole content, so it may change
|
|
92
92
|
// when anything in the content does — a row above the slot entering pushes every row down, and run
|
|
93
93
|
// backwards, leaving it pulls them up. The cut throws away the cells that hold rode on, so it is
|
|
94
|
-
// told to the frame (`RenderOptions.
|
|
95
|
-
options.
|
|
94
|
+
// told to the frame (`RenderOptions.onValidity`).
|
|
95
|
+
options.onValidity?.({ validFrom: Segment.validFrom(drawn), validUntil: Segment.validUntil(drawn) });
|
|
96
96
|
for (let r = 0; r < this.height; r++) {
|
|
97
97
|
const line = lines[this.row + r] ?? [];
|
|
98
98
|
const shown = Segment.divide(line, [start, start + width - blank])[1] ?? [];
|
|
@@ -75,8 +75,8 @@ export declare class Spinner implements Animation<Renderable & Measurable> {
|
|
|
75
75
|
private readonly _ascii;
|
|
76
76
|
/**
|
|
77
77
|
* The spinner drawn at the frame's time, its cells saying the hold it is in
|
|
78
|
-
* on the host's clock (`
|
|
79
|
-
* draws, where `
|
|
78
|
+
* on the host's clock (`stampValidityFrame`) — exactly, for the frames the output
|
|
79
|
+
* draws, where `validUntil` must answer for both. Under reduced motion it
|
|
80
80
|
* is the spinner reduced, which never turns (`shownAt`).
|
|
81
81
|
*/
|
|
82
82
|
private readonly _placed;
|
|
@@ -109,9 +109,9 @@ export declare class Spinner implements Animation<Renderable & Measurable> {
|
|
|
109
109
|
* output keeps its own interval. An early answer, on the output that draws
|
|
110
110
|
* the other one, which the contract allows; the drawn cells carry the exact one.
|
|
111
111
|
*/
|
|
112
|
-
|
|
112
|
+
validUntil(t: number): number;
|
|
113
113
|
/** When the spinner drawn at `t` began to be drawn: the later of its two sequences' answers, by the same argument. */
|
|
114
|
-
|
|
114
|
+
validFrom(t: number): number;
|
|
115
115
|
private _render;
|
|
116
116
|
/**
|
|
117
117
|
* The frame in progress and the label as one text, as Rich's
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
* frame forever, which a paused timeline is and a rate is not, and the
|
|
47
47
|
* timeline refuses it.
|
|
48
48
|
*/
|
|
49
|
-
import { Animation, frameTimeOf,
|
|
49
|
+
import { Animation, frameTimeOf, validityOf, shownAt, stampValidityFrame } from "../core/animation.js";
|
|
50
50
|
import { Segment } from "../core/segment.js";
|
|
51
51
|
import { NULL_STYLE } from "../core/style.js";
|
|
52
52
|
import { RichText } from "../core/text.js";
|
|
@@ -88,8 +88,8 @@ export class Spinner {
|
|
|
88
88
|
_ascii;
|
|
89
89
|
/**
|
|
90
90
|
* The spinner drawn at the frame's time, its cells saying the hold it is in
|
|
91
|
-
* on the host's clock (`
|
|
92
|
-
* draws, where `
|
|
91
|
+
* on the host's clock (`stampValidityFrame`) — exactly, for the frames the output
|
|
92
|
+
* draws, where `validUntil` must answer for both. Under reduced motion it
|
|
93
93
|
* is the spinner reduced, which never turns (`shownAt`).
|
|
94
94
|
*/
|
|
95
95
|
_placed;
|
|
@@ -113,7 +113,7 @@ export class Spinner {
|
|
|
113
113
|
this._placed = this._frame((played, options) => {
|
|
114
114
|
const t = frameTimeOf(options);
|
|
115
115
|
const shown = shownAt(played, t, options);
|
|
116
|
-
return { value: shown.value,
|
|
116
|
+
return { value: shown.value, validity: validityOf(shown, t) };
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
119
|
get frames() {
|
|
@@ -150,9 +150,9 @@ export class Spinner {
|
|
|
150
150
|
const drawn = (options) => drawable(options, this._named, this._ascii, sequenceGlyphs);
|
|
151
151
|
return {
|
|
152
152
|
render: (options) => {
|
|
153
|
-
const { value,
|
|
153
|
+
const { value, validity } = choose(drawn(options).played, options);
|
|
154
154
|
const segments = this._render(value, options);
|
|
155
|
-
return
|
|
155
|
+
return validity === undefined ? segments : stampValidityFrame(segments, validity);
|
|
156
156
|
},
|
|
157
157
|
// Measured at the frames' one width, the widest frame's, so a column
|
|
158
158
|
// holding it never narrows as it turns, and never offered less than
|
|
@@ -172,12 +172,12 @@ export class Spinner {
|
|
|
172
172
|
* output keeps its own interval. An early answer, on the output that draws
|
|
173
173
|
* the other one, which the contract allows; the drawn cells carry the exact one.
|
|
174
174
|
*/
|
|
175
|
-
|
|
176
|
-
return Math.min(this._named.played.
|
|
175
|
+
validUntil(t) {
|
|
176
|
+
return Math.min(this._named.played.validUntil(t), this._ascii.played.validUntil(t));
|
|
177
177
|
}
|
|
178
178
|
/** When the spinner drawn at `t` began to be drawn: the later of its two sequences' answers, by the same argument. */
|
|
179
|
-
|
|
180
|
-
return Math.max(this._named.played.
|
|
179
|
+
validFrom(t) {
|
|
180
|
+
return Math.max(this._named.played.validFrom(t), this._ascii.played.validFrom(t));
|
|
181
181
|
}
|
|
182
182
|
*_render(frame, options) {
|
|
183
183
|
yield* render(this._line(frame, options), options);
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
* Syntax — renders source code with basic syntax highlighting.
|
|
3
3
|
* Uses built-in tokenization (no external dependency).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Colors are names in the console's theme (`syntax.keyword`,
|
|
6
6
|
* `syntax.line_number`, …), not a per-instance palette: a theme is how every
|
|
7
7
|
* other renderable here is restyled, and a second styling vocabulary on this
|
|
8
|
-
* one class would be a second answer to "what
|
|
8
|
+
* one class would be a second answer to "what color is a keyword".
|
|
9
9
|
*/
|
|
10
10
|
import { Segment } from "../core/segment.js";
|
|
11
11
|
import { type Measurable, type Renderable, type RenderOptions } from "../core/protocol.js";
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
* Syntax — renders source code with basic syntax highlighting.
|
|
3
3
|
* Uses built-in tokenization (no external dependency).
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Colors are names in the console's theme (`syntax.keyword`,
|
|
6
6
|
* `syntax.line_number`, …), not a per-instance palette: a theme is how every
|
|
7
7
|
* other renderable here is restyled, and a second styling vocabulary on this
|
|
8
|
-
* one class would be a second answer to "what
|
|
8
|
+
* one class would be a second answer to "what color is a keyword".
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { escaped } from "../core/bidi.js";
|
|
11
|
+
import { cellLen, expandTabs, parseTabSize, unicodeEscape } from "../core/cells.js";
|
|
11
12
|
import { Segment } from "../core/segment.js";
|
|
12
13
|
import { RichText } from "../core/text.js";
|
|
13
14
|
import { drawable, groundedStyle, getStyle, withBoundedWidth, withCellWidth, } from "../core/protocol.js";
|
|
@@ -89,7 +90,11 @@ export class Syntax {
|
|
|
89
90
|
this.wordWrap = options?.wordWrap ?? false;
|
|
90
91
|
const tabSize = parseTabSize(options?.tabSize ?? 4);
|
|
91
92
|
this.tabSize = tabSize;
|
|
92
|
-
|
|
93
|
+
// Code on show: what the wire would drop is escaped, and an explicit bidi
|
|
94
|
+
// control with it. That is the Trojan Source attack: the order and the lines on
|
|
95
|
+
// screen differing from what the compiler reads. A joiner stays, since a Persian
|
|
96
|
+
// comment or an emoji string needs it. Only a CRLF's CR goes, with its line ending.
|
|
97
|
+
this._lines = expandTabs(escaped(code.replace(/\r\n/g, "\n"), unicodeEscape), tabSize).text.split("\n");
|
|
93
98
|
}
|
|
94
99
|
/**
|
|
95
100
|
* The lines shown, as a 0-based half-open slice of `_lines`, and the number
|
|
@@ -6,7 +6,7 @@ import { Segment } from "../core/segment.js";
|
|
|
6
6
|
import { NULL_STYLE } from "../core/style.js";
|
|
7
7
|
import { HEAVY_HEAD } from "../core/box.js";
|
|
8
8
|
import { RichText } from "../core/text.js";
|
|
9
|
-
import { EmbeddedText, embed,
|
|
9
|
+
import { EmbeddedText, embed, mounted } from "./embed.js";
|
|
10
10
|
import { Padding, normalizePadding } from "./padding.js";
|
|
11
11
|
import { exactWeights, ratioDistribute, ratioReduce } from "./ratio.js";
|
|
12
12
|
import { getStyle, render, stackedHeight, withBoundedWidth, withCellWidth } from "../core/protocol.js";
|
|
@@ -367,9 +367,9 @@ export class Table {
|
|
|
367
367
|
// An empty title draws no row, as the reference's `if self.title` draws
|
|
368
368
|
// none; markup that styles nothing is a title, and draws a blank one.
|
|
369
369
|
const titleVal = options?.title;
|
|
370
|
-
this._title =
|
|
370
|
+
this._title = mounted(titleVal) ? new EmbeddedText(titleVal) : undefined;
|
|
371
371
|
const captionVal = options?.caption;
|
|
372
|
-
this._caption =
|
|
372
|
+
this._caption = mounted(captionVal) ? new EmbeddedText(captionVal) : undefined;
|
|
373
373
|
// A declared width is the table's size, not a ceiling on it: the
|
|
374
374
|
// reference's `expand` is `self._expand or self.width is not None`, and a
|
|
375
375
|
// port that sized to content inside it drew Rich code narrower than Rich.
|
|
@@ -454,11 +454,12 @@ export class Table {
|
|
|
454
454
|
// that is all it styles: the reference reads it as `table_style` for the
|
|
455
455
|
// frame and nowhere else, so a cell is untouched by it.
|
|
456
456
|
const borderStyle = getStyle(options, this.style).add(getStyle(options, this.borderStyle));
|
|
457
|
-
const border = borderStyle.isNull ? undefined : borderStyle;
|
|
458
457
|
// The one division of the width every row below is measured against.
|
|
459
458
|
const outerWidth = this._outerWidth(options);
|
|
460
459
|
const geometry = this._geometry(options, outerWidth);
|
|
461
460
|
const edge = geometry.edge === 1;
|
|
461
|
+
// Only an edge closes a frame: without one, a table's rules are not a border.
|
|
462
|
+
const border = box && edge ? box.frame(borderStyle) : borderStyle.isNull ? undefined : borderStyle;
|
|
462
463
|
// Title
|
|
463
464
|
if (this._title) {
|
|
464
465
|
yield* this._renderTitle(options, this._title, geometry.totalWidth, this.titleStyle, this.titleJustify);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* an inspector session pausing on exceptions — would have to pause on every
|
|
14
14
|
* throw, caught ones included, to serve `new Traceback(caughtError)`, and it
|
|
15
15
|
* cannot exist in a browser at all. Nor is there a `width` or `theme`: those
|
|
16
|
-
* sized and
|
|
16
|
+
* sized and colored a source-code excerpt this renderer does not produce.
|
|
17
17
|
*/
|
|
18
18
|
import { Segment } from "../core/segment.js";
|
|
19
19
|
import { type Renderable, type RenderOptions } from "../core/protocol.js";
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* an inspector session pausing on exceptions — would have to pause on every
|
|
14
14
|
* throw, caught ones included, to serve `new Traceback(caughtError)`, and it
|
|
15
15
|
* cannot exist in a browser at all. Nor is there a `width` or `theme`: those
|
|
16
|
-
* sized and
|
|
16
|
+
* sized and colored a source-code excerpt this renderer does not produce.
|
|
17
17
|
*/
|
|
18
18
|
import { Segment } from "../core/segment.js";
|
|
19
19
|
import { RichText } from "../core/text.js";
|
package/dist/renderables/tree.js
CHANGED
|
@@ -18,15 +18,15 @@ const ASCII_GUIDES = { fork: "+-- ", end: "`-- ", continue: "| ", space: "
|
|
|
18
18
|
* The guide attributes a glyph set stands for, switched off on the guide itself
|
|
19
19
|
* as Rich's `remove_guide_styles` does: a bold guide is drawn heavy, not bold.
|
|
20
20
|
*/
|
|
21
|
-
const REMOVE_GUIDE_STYLES = new Style({ bold: false,
|
|
21
|
+
const REMOVE_GUIDE_STYLES = new Style({ bold: false, doubleUnderline: false });
|
|
22
22
|
const guideGlyphs = (glyphs) => Object.values(glyphs).join("");
|
|
23
23
|
/**
|
|
24
24
|
* The glyphs a column of guide is drawn with, read off its resolved guide style
|
|
25
|
-
* as Rich does: heavy when bold, double when
|
|
25
|
+
* as Rich does: heavy when bold, double when doubleUnderline, light otherwise — and
|
|
26
26
|
* ASCII whenever the terminal cannot draw the chosen set.
|
|
27
27
|
*/
|
|
28
28
|
function glyphsFor(options, style) {
|
|
29
|
-
const weight = style.bold === true ? HEAVY_GUIDES : style.
|
|
29
|
+
const weight = style.bold === true ? HEAVY_GUIDES : style.doubleUnderline === true ? DOUBLE_GUIDES : LIGHT_GUIDES;
|
|
30
30
|
return drawable(options, weight, ASCII_GUIDES, guideGlyphs);
|
|
31
31
|
}
|
|
32
32
|
/** A row a label is known to draw, unread. */
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
* number the time is turned into first: a frame's stamp says when it changes
|
|
21
21
|
* on the host's clock, which only `Timeline.run` can carry it back onto —
|
|
22
22
|
* paused, never; backwards, at the hold it is about to drop under.
|
|
23
|
-
* [LAW:single-enforcer] `
|
|
23
|
+
* [LAW:single-enforcer] `drawn` is the one place the time, the timeline
|
|
24
24
|
* and the reader's preference for motion are read, for every function.
|
|
25
25
|
*
|
|
26
26
|
* `frames <seconds> <frame> <seconds> <frame> …` is a `FrameSequence`
|
|
@@ -29,78 +29,109 @@
|
|
|
29
29
|
* arguments on every evaluation, so the sequence is prepared on every one:
|
|
30
30
|
* a template has nowhere to keep it, and keeping it here would be the memo
|
|
31
31
|
* keyed on the arguments that `FrameSequence` is instead of. `stepped <seconds>
|
|
32
|
-
* <color> <seconds> <color> …` is the
|
|
33
|
-
*
|
|
34
|
-
* nests where a
|
|
32
|
+
* <color> <seconds> <color> …` is the color in progress at the moment, a
|
|
33
|
+
* color value like every color function's (`./color-funcs.ts`), so it
|
|
34
|
+
* nests where a color goes — `fg (stepped …)`, `ensureContrast (stepped …) $bg
|
|
35
35
|
* 4.5` — and the ground it must read on is the template's to name, as it
|
|
36
|
-
* is for any
|
|
36
|
+
* is for any color. Either argument list is one float/value cycle end to
|
|
37
37
|
* end, so the engine's `alternating` gate types every slot and lifts each
|
|
38
38
|
* string frame to a fragment; the pairing — a trailing hold with no frame or
|
|
39
|
-
*
|
|
39
|
+
* color — is parsed in `pairs`, once. [LAW:types-are-the-program]
|
|
40
40
|
*
|
|
41
41
|
* The rest start at a moment the template names, on the timeline's clock —
|
|
42
42
|
* a field of the host's state, the moment a value changed — and each is the
|
|
43
43
|
* animation `Timeline.play(start)` runs, so a start is a timeline like any
|
|
44
44
|
* other and nothing here offsets a time by hand. `tween <seconds> <ease>
|
|
45
45
|
* <start> <from> <to>` is a number eased from one value to another and held
|
|
46
|
-
* (`core/tween.ts`), its ease spelled by name (`
|
|
46
|
+
* (`core/tween.ts`), its ease spelled by name (`parseEasing`); `loop <seconds>
|
|
47
47
|
* <start>` is the way through a period, 0 to 1 and round again — two
|
|
48
48
|
* cells started a step apart are a stagger. Each is a number, so it goes
|
|
49
|
-
* wherever a number goes: a
|
|
49
|
+
* wherever a number goes: a color tween is `ramp (tween …) "linear" 0 $from
|
|
50
50
|
* 1 $to` and a ramp scrolling is `ramp (loop …) …`, because `ColorRamp` is
|
|
51
|
-
* the one place two
|
|
51
|
+
* the one place two colors are blended and a color tween is a two-stop
|
|
52
52
|
* ramp read over time (`ColorRamp.over`). [LAW:one-source-of-truth] A
|
|
53
53
|
* second blender here would be a second answer to what lies between two
|
|
54
|
-
*
|
|
54
|
+
* colors. `glyphs <name> <start> <fragment>` is the fragment through a
|
|
55
55
|
* glyph effect from the catalogue (`GLYPH_EFFECT_CATALOGUE`), at its
|
|
56
56
|
* defaults, before any render (`reglyphText`). Every argument list is an
|
|
57
57
|
* exact arity of typed slots, so a slot of the wrong kind fails at the gate.
|
|
58
58
|
*
|
|
59
59
|
* Every function says when what it drew changes, so a host paints a
|
|
60
|
-
* template while it moves and not after
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
60
|
+
* template while it moves and not after — and says it only for what the
|
|
61
|
+
* output depends on. A number or a color has no cells to carry a hold, and
|
|
62
|
+
* a fragment's cells lose theirs the moment it is flattened (`printf "%s"`),
|
|
63
|
+
* so no function stamps cells or tells the frame itself. Each marks its
|
|
64
|
+
* return with the hold its value is in (`marked`, the engine's evaluation
|
|
65
|
+
* provenance), and the engine carries the mark beside the value into every
|
|
66
|
+
* variable, dot and function the value passes through, reporting it where
|
|
67
|
+
* the output depends on it. `emitted` is where a template's cells take a
|
|
68
|
+
* hold: every fragment the template emits, stamped with the holds of the
|
|
69
|
+
* marked values its action read. `decided` is the route for a hold no cell
|
|
70
|
+
* can carry, told to the frame (`TemplateFrame.onValidity`): a mark an
|
|
71
|
+
* `if`/`with`/`range` consumed, whichever arm it took, because the frame may
|
|
72
|
+
* show cells for it later and must say when without a cell to say it on, as
|
|
73
|
+
* a placed animation of no cells does (`placed`) — and, by the same rule, a
|
|
74
|
+
* mark a writing function or a throwing action read; `EngineConfig.decided`
|
|
75
|
+
* is the authority on when it is called. A mark bound somewhere nobody reads
|
|
76
|
+
* is reported nowhere, so a value a template computes and never draws or
|
|
77
|
+
* decides on tells the frame nothing (rich-animation-27tq.0gd). Early, never
|
|
78
|
+
* late: an emission may carry a hold it did not strictly need, and a hold
|
|
79
|
+
* the output depends on is never dropped. [LAW:single-enforcer]
|
|
80
|
+
*
|
|
81
|
+
* The functions and the two hooks go into the host's engine config together,
|
|
82
|
+
* by `withAnimation`: the functions wired without the hooks would compile,
|
|
83
|
+
* draw and never say they move. [LAW:no-silent-failure]
|
|
66
84
|
*/
|
|
67
|
-
import type
|
|
85
|
+
import { type EngineConfig } from "@promptctl/go-template-js";
|
|
68
86
|
import type { RenderOptions } from "../core/protocol.js";
|
|
87
|
+
import type { RichText } from "../core/text.js";
|
|
69
88
|
import { Timeline } from "../core/timeline.js";
|
|
70
|
-
/** What
|
|
71
|
-
export interface
|
|
89
|
+
/** What the animation functions are drawn on, beside the frame each evaluation is handed. */
|
|
90
|
+
export interface AnimationOptions {
|
|
72
91
|
/** The timeline to draw on, read once per call; the frame's own time when omitted. */
|
|
73
92
|
readonly timeline?: () => Timeline;
|
|
74
93
|
}
|
|
75
94
|
/**
|
|
76
95
|
* The frame a template is evaluated for, in the fields a render's options
|
|
77
|
-
* carry under the same names: `time` in seconds, `
|
|
78
|
-
*
|
|
96
|
+
* carry under the same names: `time` in seconds, `onValidity`, told the hold of
|
|
97
|
+
* an animated value the output may depend on with no cell to carry it — one
|
|
98
|
+
* a decision read, whichever arm it took, a writing function's input, a
|
|
99
|
+
* throwing action's (the engine's `decided`) — and the reader's preferences,
|
|
79
100
|
* `reducedMotion`, and `asciiOnly`, which the glyphs an effect picks for
|
|
80
101
|
* itself go through. They arrive with every frame and nowhere else, so a
|
|
81
102
|
* template drawn in an `App` is drawn as the app's preferences say.
|
|
82
103
|
* [LAW:one-source-of-truth]
|
|
83
104
|
*
|
|
84
|
-
* `time` is on the clock `
|
|
85
|
-
* `
|
|
105
|
+
* `time` is on the clock `AnimationOptions.timeline` maps from, and
|
|
106
|
+
* `onValidity` hears on that clock. A host outside rich-js hands its own clock's
|
|
86
107
|
* time. Inside a rich-js frame the time is the frame's, which its host's
|
|
87
108
|
* timeline has already mapped, so a template drawn there registers no
|
|
88
109
|
* `timeline` and is handed `templateFrame(options)`.
|
|
89
110
|
*/
|
|
90
|
-
export interface TemplateFrame extends Pick<RenderOptions, "
|
|
111
|
+
export interface TemplateFrame extends Pick<RenderOptions, "onValidity" | "reducedMotion" | "asciiOnly"> {
|
|
91
112
|
readonly time: number;
|
|
92
113
|
}
|
|
93
114
|
/** The frame a renderable is drawn in, as the frame a template it evaluates there is drawn for. */
|
|
94
115
|
export declare function templateFrame(options: RenderOptions): TemplateFrame;
|
|
95
116
|
/**
|
|
96
|
-
*
|
|
97
|
-
* the frame `frame` reports when
|
|
98
|
-
* seconds, from whatever zero the
|
|
99
|
-
* `options.timeline`, and each
|
|
117
|
+
* `config` with `frames`, `stepped`, `tween`, `loop` and `glyphs` registered
|
|
118
|
+
* beside its own functions, each drawn for the frame `frame` reports when
|
|
119
|
+
* the template is evaluated — its time in seconds, from whatever zero the
|
|
120
|
+
* host counts from — through `options.timeline`, and each marking its
|
|
121
|
+
* return with the hold it is in there; and with the two hooks that carry
|
|
122
|
+
* those holds to the cells (`emitted`) and the frame (`decided`) installed
|
|
123
|
+
* over any `config` already has, which still hear everything they did. One
|
|
124
|
+
* call, so the functions and the hooks that report for them cannot be wired
|
|
125
|
+
* apart: the functions alone would compile, draw, and never say they move.
|
|
126
|
+
* [LAW:types-are-the-program] [LAW:no-silent-failure] [LAW:composability]
|
|
127
|
+
* A `config` that already has one of the five names is refused, which is
|
|
128
|
+
* also what a second `withAnimation` over its own result meets: its template
|
|
129
|
+
* calls would otherwise reach these with no word said.
|
|
130
|
+
*
|
|
100
131
|
* The functions exist whatever `frame` returns, so a template compiles once
|
|
101
132
|
* and is evaluated at every moment the host draws. In a frame that says
|
|
102
133
|
* `reducedMotion` each draws its animation reduced (`Animation.reduced`): a
|
|
103
134
|
* loop at its start, a one-shot cut from where it starts to where it arrives
|
|
104
135
|
* when it starts.
|
|
105
136
|
*/
|
|
106
|
-
export declare function
|
|
137
|
+
export declare function withAnimation(config: EngineConfig<RichText>, frame: () => TemplateFrame, options?: AnimationOptions): EngineConfig<RichText>;
|