@promptctl/rich-js 0.24.0 → 0.25.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 -0
- package/THIRD-PARTY-NOTICES +29 -1
- package/dist/core/anchor.d.ts +5 -0
- package/dist/core/anchor.js +11 -4
- package/dist/core/animation.d.ts +243 -0
- package/dist/core/animation.js +375 -0
- package/dist/core/ansi.js +2 -2
- package/dist/core/box.d.ts +7 -7
- package/dist/core/cell-widths.d.ts +9 -0
- package/dist/core/cell-widths.js +140 -0
- package/dist/core/cells.d.ts +40 -24
- package/dist/core/cells.js +151 -66
- package/dist/core/clock.d.ts +2 -2
- package/dist/core/clock.js +6 -4
- package/dist/core/color.d.ts +27 -10
- package/dist/core/color.js +21 -29
- package/dist/core/console.d.ts +28 -17
- package/dist/core/console.js +48 -43
- package/dist/core/easing.d.ts +140 -10
- package/dist/core/easing.js +328 -50
- package/dist/core/emoji.d.ts +1 -1
- package/dist/core/emoji.js +1 -2
- package/dist/core/export-html.js +2 -1
- package/dist/core/export-lines.js +3 -3
- package/dist/core/highlighter.d.ts +9 -8
- package/dist/core/highlighter.js +3 -2
- package/dist/core/json.js +3 -2
- package/dist/core/markup.js +16 -12
- package/dist/core/measure.js +3 -3
- package/dist/core/memo.d.ts +11 -2
- package/dist/core/memo.js +16 -0
- package/dist/core/oklch.js +17 -6
- package/dist/core/osc8.d.ts +1 -1
- package/dist/core/osc8.js +4 -5
- package/dist/core/paint.d.ts +2 -1
- package/dist/core/paint.js +4 -3
- package/dist/core/pattern.d.ts +21 -0
- package/dist/core/pattern.js +21 -0
- package/dist/core/place.js +2 -1
- package/dist/core/pretty.js +11 -12
- package/dist/core/protocol.d.ts +136 -21
- package/dist/core/protocol.js +203 -16
- package/dist/core/render.d.ts +15 -2
- package/dist/core/render.js +27 -6
- package/dist/core/segment.d.ts +31 -6
- package/dist/core/segment.js +68 -53
- package/dist/core/spinnerData.d.ts +1 -1
- package/dist/core/state.d.ts +53 -0
- package/dist/core/state.js +82 -0
- package/dist/core/strip.d.ts +11 -13
- package/dist/core/strip.js +126 -113
- package/dist/core/style.d.ts +47 -14
- package/dist/core/style.js +74 -34
- package/dist/core/text.d.ts +5 -8
- package/dist/core/text.js +133 -133
- package/dist/core/timeline.d.ts +109 -0
- package/dist/core/timeline.js +180 -0
- package/dist/core/tween.d.ts +49 -0
- package/dist/core/tween.js +71 -0
- package/dist/core/view.d.ts +92 -0
- package/dist/core/view.js +83 -0
- package/dist/host/app.d.ts +49 -21
- package/dist/host/app.js +72 -38
- package/dist/host/input.js +3 -4
- package/dist/index.d.ts +30 -15
- package/dist/index.js +20 -6
- package/dist/node/traceback.js +4 -3
- package/dist/renderables/change.d.ts +42 -0
- package/dist/renderables/change.js +112 -0
- package/dist/renderables/columns.d.ts +1 -1
- package/dist/renderables/columns.js +3 -3
- package/dist/renderables/constrain.js +2 -1
- package/dist/renderables/effect.d.ts +155 -92
- package/dist/renderables/effect.js +203 -136
- package/dist/renderables/effects.d.ts +137 -24
- package/dist/renderables/effects.js +276 -113
- package/dist/renderables/embed.d.ts +1 -1
- package/dist/renderables/embed.js +18 -9
- package/dist/renderables/flexStrip.js +2 -1
- package/dist/renderables/frames.d.ts +45 -43
- package/dist/renderables/frames.js +57 -45
- package/dist/renderables/glyph-effect.d.ts +158 -0
- package/dist/renderables/glyph-effect.js +237 -0
- package/dist/renderables/glyph-effects.d.ts +147 -0
- package/dist/renderables/glyph-effects.js +283 -0
- package/dist/renderables/group.d.ts +1 -1
- package/dist/renderables/group.js +2 -2
- package/dist/renderables/html-entities.d.ts +8 -0
- package/dist/renderables/html-entities.js +386 -0
- package/dist/renderables/layout.d.ts +10 -9
- package/dist/renderables/layout.js +42 -35
- package/dist/renderables/lifecycle.d.ts +77 -0
- package/dist/renderables/lifecycle.js +132 -0
- package/dist/renderables/list-view.d.ts +2 -2
- package/dist/renderables/list-view.js +11 -8
- package/dist/renderables/live.d.ts +36 -21
- package/dist/renderables/live.js +89 -42
- package/dist/renderables/markdown-parse.d.ts +109 -0
- package/dist/renderables/markdown-parse.js +1427 -0
- package/dist/renderables/markdown-url.d.ts +19 -0
- package/dist/renderables/markdown-url.js +314 -0
- package/dist/renderables/markdown.d.ts +5 -7
- package/dist/renderables/markdown.js +356 -683
- package/dist/renderables/padding.d.ts +7 -20
- package/dist/renderables/padding.js +29 -50
- package/dist/renderables/panel.d.ts +30 -32
- package/dist/renderables/panel.js +65 -109
- package/dist/renderables/progress.d.ts +83 -32
- package/dist/renderables/progress.js +186 -90
- package/dist/renderables/progressBar.d.ts +22 -12
- package/dist/renderables/progressBar.js +33 -10
- package/dist/renderables/prompt.js +3 -2
- package/dist/renderables/python-space.d.ts +13 -0
- package/dist/renderables/python-space.js +25 -0
- package/dist/renderables/scroll.d.ts +50 -0
- package/dist/renderables/scroll.js +106 -0
- package/dist/renderables/spinner.d.ts +57 -24
- package/dist/renderables/spinner.js +101 -49
- package/dist/renderables/status.js +1 -1
- package/dist/renderables/syntax.d.ts +10 -9
- package/dist/renderables/syntax.js +5 -3
- package/dist/renderables/table.d.ts +48 -46
- package/dist/renderables/table.js +170 -208
- package/dist/renderables/traceback.d.ts +3 -3
- package/dist/renderables/traceback.js +12 -10
- package/dist/renderables/tree.d.ts +28 -25
- package/dist/renderables/tree.js +108 -58
- package/dist/renderables/viewport.d.ts +77 -38
- package/dist/renderables/viewport.js +156 -72
- package/dist/template-bindings/animation-funcs.d.ts +78 -9
- package/dist/template-bindings/animation-funcs.js +132 -14
- package/dist/template-bindings/index.d.ts +5 -5
- package/dist/template-bindings/index.js +7 -6
- package/dist/themes/ramp.d.ts +62 -4
- package/dist/themes/ramp.js +82 -4
- package/dist/themes/registry.js +5 -7
- package/dist/widgets/button.js +3 -2
- package/dist/widgets/checkbox.js +4 -3
- package/dist/widgets/dropdown.d.ts +3 -1
- package/dist/widgets/dropdown.js +20 -15
- package/dist/widgets/event-router.js +4 -2
- package/dist/widgets/focus-manager.d.ts +23 -14
- package/dist/widgets/focus-manager.js +34 -33
- package/dist/widgets/hit.d.ts +6 -0
- package/dist/widgets/hit.js +8 -1
- package/dist/widgets/index.d.ts +1 -1
- package/dist/widgets/observable.d.ts +23 -0
- package/dist/widgets/observable.js +43 -0
- package/dist/widgets/slider.d.ts +1 -1
- package/dist/widgets/slider.js +12 -3
- package/dist/widgets/static-item.d.ts +1 -1
- package/dist/widgets/static-item.js +6 -7
- package/dist/widgets/text-input.d.ts +53 -47
- package/dist/widgets/text-input.js +456 -399
- package/dist/widgets/themed-widget.js +2 -1
- package/dist/widgets/toggle.js +4 -3
- package/dist/widgets/types.d.ts +10 -4
- package/dist/widgets/types.js +8 -2
- package/dist/widgets/widget-app.d.ts +32 -6
- package/dist/widgets/widget-app.js +74 -27
- package/dist/widgets/widget-base.d.ts +2 -2
- package/dist/widgets/widget-base.js +29 -21
- package/package.json +9 -5
package/dist/core/markup.js
CHANGED
|
@@ -21,6 +21,8 @@ import { cellLen } from "./cells.js";
|
|
|
21
21
|
import { Style, StyleSyntaxError } from "./style.js";
|
|
22
22
|
import { RichText, stripControlChars } from "./text.js";
|
|
23
23
|
import { emojiReplace } from "./emoji.js";
|
|
24
|
+
import { pattern } from "./pattern.js";
|
|
25
|
+
import { State } from "./state.js";
|
|
24
26
|
// --- Tag ---
|
|
25
27
|
export class Tag {
|
|
26
28
|
name;
|
|
@@ -159,7 +161,7 @@ function excerpt(text, index) {
|
|
|
159
161
|
*/
|
|
160
162
|
export function escape(text) {
|
|
161
163
|
return text
|
|
162
|
-
.replace(ESCAPE_RE, (_, run, live) => live === undefined ? `${run}\\[` : `${run}${run}\\[`)
|
|
164
|
+
.replace(new RegExp(ESCAPE_RE.source, "g"), (_, run, live) => live === undefined ? `${run}\\[` : `${run}${run}\\[`)
|
|
163
165
|
.replace(TRAILING_RUN_RE, "$&$&");
|
|
164
166
|
}
|
|
165
167
|
// --- render ---
|
|
@@ -188,18 +190,18 @@ export function escape(text) {
|
|
|
188
190
|
// run, on exactly the untrusted text `escape` is for.
|
|
189
191
|
const TAG_BODY = String.raw `[a-z#/@][^[]*?\]`;
|
|
190
192
|
const RUN = String.raw `(?<!\\)(\\*)`;
|
|
191
|
-
const TAG_RE = new RegExp(String.raw `${RUN}(\[${TAG_BODY})
|
|
193
|
+
const TAG_RE = pattern(new RegExp(String.raw `${RUN}(\[${TAG_BODY})`));
|
|
192
194
|
/**
|
|
193
195
|
* Every bracket and the run in front of it; the empty second group is set when
|
|
194
196
|
* a tag starts there or could, once more text is joined after the end. It is an
|
|
195
197
|
* alternation rather than `(…)?` because a quantified group may not match empty.
|
|
196
198
|
*/
|
|
197
|
-
const ESCAPE_RE = new RegExp(String.raw `${RUN}\[(?:(?=${TAG_BODY}|(?:[a-z#/@][^[\]]*)?$)()|)
|
|
198
|
-
const TRAILING_RUN_RE = /(?<!\\)
|
|
199
|
+
const ESCAPE_RE = pattern(new RegExp(String.raw `${RUN}\[(?:(?=${TAG_BODY}|(?:[a-z#/@][^[\]]*)?$)()|)`));
|
|
200
|
+
const TRAILING_RUN_RE = pattern(/(?<!\\)\\+$/);
|
|
199
201
|
function tokenize(markup) {
|
|
200
202
|
const tokens = [];
|
|
201
203
|
let position = 0;
|
|
202
|
-
for (const match of markup.matchAll(TAG_RE)) {
|
|
204
|
+
for (const match of markup.matchAll(new RegExp(TAG_RE.source, "g"))) {
|
|
203
205
|
const run = match[1];
|
|
204
206
|
const captured = match[2];
|
|
205
207
|
let start = match.index;
|
|
@@ -292,9 +294,9 @@ function findLastIndex(items, match) {
|
|
|
292
294
|
// could never fire. This tracked `[A-Za-z]` while `TAG_RE` wrongly admitted
|
|
293
295
|
// uppercase, which is the same drift, one subset down (rich-markup-sec).
|
|
294
296
|
const PLUGIN_TAG_NAME_SRC = "[a-z][A-Za-z0-9_-]*";
|
|
295
|
-
const LEGAL_PLUGIN_TAG_NAME = new RegExp(`^${PLUGIN_TAG_NAME_SRC}$`);
|
|
297
|
+
const LEGAL_PLUGIN_TAG_NAME = pattern(new RegExp(`^${PLUGIN_TAG_NAME_SRC}$`));
|
|
296
298
|
export class MarkupRegistry {
|
|
297
|
-
_handlers = new Map();
|
|
299
|
+
_handlers = new State(new Map());
|
|
298
300
|
register(name, handler) {
|
|
299
301
|
// [LAW:no-silent-failure] Registration used to accept any string, including
|
|
300
302
|
// names markup can never address (`a.b` stops the tag scan at the dot), and
|
|
@@ -305,16 +307,18 @@ export class MarkupRegistry {
|
|
|
305
307
|
if (isReservedTagName(name)) {
|
|
306
308
|
throw new MarkupError(`Cannot register markup tag "${name}": name is reserved by a built-in style.`);
|
|
307
309
|
}
|
|
308
|
-
this._handlers.set(name, handler);
|
|
310
|
+
this._handlers.set(new Map(this._handlers.get()).set(name, handler));
|
|
309
311
|
}
|
|
310
312
|
unregister(name) {
|
|
311
|
-
this._handlers.
|
|
313
|
+
const handlers = new Map(this._handlers.get());
|
|
314
|
+
handlers.delete(name);
|
|
315
|
+
this._handlers.set(handlers);
|
|
312
316
|
}
|
|
313
317
|
has(name) {
|
|
314
|
-
return this._handlers.has(name);
|
|
318
|
+
return this._handlers.get().has(name);
|
|
315
319
|
}
|
|
316
320
|
get(name) {
|
|
317
|
-
return this._handlers.get(name);
|
|
321
|
+
return this._handlers.get().get(name);
|
|
318
322
|
}
|
|
319
323
|
}
|
|
320
324
|
// [LAW:one-source-of-truth] Reserved-name detection delegates to Style.parse —
|
|
@@ -356,7 +360,7 @@ function isSpace(c) {
|
|
|
356
360
|
// continues with the whitespace that introduces attributes. Anything else —
|
|
357
361
|
// `[table.header]`, `[table=x]` — is the built-in dialect's, and falls through
|
|
358
362
|
// exactly as an unregistered name would.
|
|
359
|
-
const PLUGIN_TAG_HEAD = new RegExp(`^(${PLUGIN_TAG_NAME_SRC})(?=$|[ \\t])`);
|
|
363
|
+
const PLUGIN_TAG_HEAD = pattern(new RegExp(`^(${PLUGIN_TAG_NAME_SRC})(?=$|[ \\t])`));
|
|
360
364
|
function parsePluginAttrs(after) {
|
|
361
365
|
// Hand-written tokenizer. Walks `key=value` pairs separated by whitespace;
|
|
362
366
|
// values may be bare, single-quoted, or double-quoted. Matches the syntax
|
package/dist/core/measure.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Measurement — min/max cell width calculation for renderables.
|
|
3
3
|
*/
|
|
4
|
-
import { isMeasurable,
|
|
4
|
+
import { drawsNothing, isMeasurable, measure } from "./protocol.js";
|
|
5
5
|
export class Measurement {
|
|
6
6
|
minimum;
|
|
7
7
|
maximum;
|
|
@@ -45,11 +45,11 @@ export class Measurement {
|
|
|
45
45
|
// `Measurement.get` answers for it — so under an unbounded offer it asks for
|
|
46
46
|
// `Infinity`, and `withBoundedWidth` refuses rather than guessing a width.
|
|
47
47
|
static get(options, renderable) {
|
|
48
|
-
if (options
|
|
48
|
+
if (drawsNothing(options))
|
|
49
49
|
return new Measurement(0, 0);
|
|
50
50
|
if (!isMeasurable(renderable))
|
|
51
51
|
return new Measurement(0, options.maxWidth);
|
|
52
|
-
const { minimum, maximum } =
|
|
52
|
+
const { minimum, maximum } = measure(renderable, options);
|
|
53
53
|
return new Measurement(minimum, Math.min(maximum, options.maxWidth)).normalize();
|
|
54
54
|
}
|
|
55
55
|
}
|
package/dist/core/memo.d.ts
CHANGED
|
@@ -12,8 +12,17 @@ export declare const MEMO_MAX = 4096;
|
|
|
12
12
|
* be a pure function of `key`, so a value recomputed after a clear is the one
|
|
13
13
|
* that was dropped.
|
|
14
14
|
*/
|
|
15
|
-
export declare class Memo<V extends NonNullable<unknown
|
|
15
|
+
export declare class Memo<V extends NonNullable<unknown>, K extends string = string> {
|
|
16
16
|
private readonly entries;
|
|
17
17
|
get size(): number;
|
|
18
|
-
get(key:
|
|
18
|
+
get(key: K, compute: (key: K) => V): V;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* `Memo`'s contract for a key that is an object rather than a string: a
|
|
22
|
+
* value computed once per key, for as long as the key lives. Held weakly, so
|
|
23
|
+
* it needs no bound — a key a host stops holding takes its entry with it.
|
|
24
|
+
*/
|
|
25
|
+
export declare class WeakMemo<V extends NonNullable<unknown>, K extends object> {
|
|
26
|
+
private readonly entries;
|
|
27
|
+
get(key: K, compute: (key: K) => V): V;
|
|
19
28
|
}
|
package/dist/core/memo.js
CHANGED
|
@@ -32,3 +32,19 @@ export class Memo {
|
|
|
32
32
|
return value;
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* `Memo`'s contract for a key that is an object rather than a string: a
|
|
37
|
+
* value computed once per key, for as long as the key lives. Held weakly, so
|
|
38
|
+
* it needs no bound — a key a host stops holding takes its entry with it.
|
|
39
|
+
*/
|
|
40
|
+
export class WeakMemo {
|
|
41
|
+
entries = new WeakMap();
|
|
42
|
+
get(key, compute) {
|
|
43
|
+
const remembered = this.entries.get(key);
|
|
44
|
+
if (remembered !== undefined)
|
|
45
|
+
return remembered;
|
|
46
|
+
const value = compute(key);
|
|
47
|
+
this.entries.set(key, value);
|
|
48
|
+
return value;
|
|
49
|
+
}
|
|
50
|
+
}
|
package/dist/core/oklch.js
CHANGED
|
@@ -96,6 +96,11 @@ function inGamut(r, g, b) {
|
|
|
96
96
|
g >= -GAMUT_EPS && g <= 1 + GAMUT_EPS &&
|
|
97
97
|
b >= -GAMUT_EPS && b <= 1 + GAMUT_EPS);
|
|
98
98
|
}
|
|
99
|
+
/** Polar (C, h°) → OKLab (a, b): the one spelling `deltaE` measures by and `toRgba` draws by. */
|
|
100
|
+
function labOf(c, h) {
|
|
101
|
+
const hRad = h * (Math.PI / 180);
|
|
102
|
+
return [c * Math.cos(hRad), c * Math.sin(hRad)];
|
|
103
|
+
}
|
|
99
104
|
// ---------------------------------------------------------------------------
|
|
100
105
|
// Oklch — the value type.
|
|
101
106
|
// ---------------------------------------------------------------------------
|
|
@@ -130,6 +135,7 @@ export class Oklch {
|
|
|
130
135
|
if (!Number.isFinite(alpha) || alpha < 0 || alpha > 1) {
|
|
131
136
|
throw new RangeError(`Oklch.alpha must be a finite number in [0,1]; got ${alpha}`);
|
|
132
137
|
}
|
|
138
|
+
this.#lab = labOf(c, h);
|
|
133
139
|
}
|
|
134
140
|
/** sRGB → linear → OKLab → polar. Pure; no I/O, no allocation beyond the result. */
|
|
135
141
|
static fromRgba(color) {
|
|
@@ -265,16 +271,21 @@ export class Oklch {
|
|
|
265
271
|
* Symmetric and pure.
|
|
266
272
|
*/
|
|
267
273
|
deltaE(other) {
|
|
268
|
-
const a =
|
|
269
|
-
const
|
|
270
|
-
return Math.hypot(this.l - other.l,
|
|
274
|
+
const [a, b] = this.#lab;
|
|
275
|
+
const [otherA, otherB] = other.#lab;
|
|
276
|
+
return Math.hypot(this.l - other.l, a - otherA, b - otherB);
|
|
271
277
|
}
|
|
278
|
+
/**
|
|
279
|
+
* This colour's OKLab a and b, kept with it: a colour matched against a
|
|
280
|
+
* palette is measured against every entry, and each entry against every
|
|
281
|
+
* colour it is matched with, so the trigonometry is paid once a colour
|
|
282
|
+
* rather than once a comparison.
|
|
283
|
+
*/
|
|
284
|
+
#lab;
|
|
272
285
|
/** Linear-sRGB coordinates for an explicit (l, C, h). Pure; `toRgba` passes
|
|
273
286
|
* already-normalized values so this never sees out-of-range inputs. */
|
|
274
287
|
toLinearRgb(l, C, h) {
|
|
275
|
-
const
|
|
276
|
-
const aLab = C * Math.cos(hRad);
|
|
277
|
-
const bLab = C * Math.sin(hRad);
|
|
288
|
+
const [aLab, bLab] = labOf(C, h);
|
|
278
289
|
const lCube = l + 0.3963377774 * aLab + 0.2158037573 * bLab;
|
|
279
290
|
const mCube = l - 0.1055613458 * aLab - 0.0638541728 * bLab;
|
|
280
291
|
const sCube = l - 0.0894841775 * aLab - 1.2914855480 * bLab;
|
package/dist/core/osc8.d.ts
CHANGED
|
@@ -49,7 +49,7 @@ export declare const OSC8_CLOSE = "\u001B]8;;\u001B\\";
|
|
|
49
49
|
* on a close. To read bytes back use `osc8Sequences`; this pattern is exported
|
|
50
50
|
* for composing into a larger one (a width measure's zero-width alternation).
|
|
51
51
|
*/
|
|
52
|
-
export declare const OSC8:
|
|
52
|
+
export declare const OSC8: import("./pattern.js").Pattern;
|
|
53
53
|
/** One OSC 8 sequence found in rendered bytes. A close has `uri === ""`. */
|
|
54
54
|
export interface Osc8Sequence {
|
|
55
55
|
/** Offset of the sequence in the scanned string. */
|
package/dist/core/osc8.js
CHANGED
|
@@ -31,15 +31,15 @@
|
|
|
31
31
|
* exact, not approximate.
|
|
32
32
|
*/
|
|
33
33
|
import { fnv1a } from "./fnv1a.js";
|
|
34
|
+
import { pattern } from "./pattern.js";
|
|
34
35
|
/**
|
|
35
36
|
* The bytes that prematurely terminate an OSC 8 sequence: ESC (`\x1b`, which
|
|
36
37
|
* begins ST `ESC \`), BEL (`\x07`), and the 8-bit ST (`\x9c`).
|
|
37
38
|
*/
|
|
38
39
|
const TERMINATORS = "\\x1b\\x07\\x9c";
|
|
39
|
-
const TERMINATOR_RE = new RegExp(`[${TERMINATORS}]`, "g");
|
|
40
40
|
/** Remove every byte that could break a URL out of its OSC 8 wrap. */
|
|
41
41
|
export function stripOscTerminators(url) {
|
|
42
|
-
return url.replace(
|
|
42
|
+
return url.replace(new RegExp(`[${TERMINATORS}]`, "g"), "");
|
|
43
43
|
}
|
|
44
44
|
/**
|
|
45
45
|
* The bytes that open a hyperlink to `url`.
|
|
@@ -62,14 +62,13 @@ export const OSC8_CLOSE = "\x1b]8;;\x1b\\";
|
|
|
62
62
|
* on a close. To read bytes back use `osc8Sequences`; this pattern is exported
|
|
63
63
|
* for composing into a larger one (a width measure's zero-width alternation).
|
|
64
64
|
*/
|
|
65
|
-
export const OSC8 = new RegExp(`\\x1b\\]8;([^;${TERMINATORS}]*);([^${TERMINATORS}]*)(?:\\x1b\\\\|\\x07|\\x9c)`);
|
|
66
|
-
const OSC8_SCAN = new RegExp(OSC8.source, "g");
|
|
65
|
+
export const OSC8 = pattern(new RegExp(`\\x1b\\]8;([^;${TERMINATORS}]*);([^${TERMINATORS}]*)(?:\\x1b\\\\|\\x07|\\x9c)`));
|
|
67
66
|
/**
|
|
68
67
|
* Every OSC 8 sequence in `text`, in order — the typed way to read rendered
|
|
69
68
|
* bytes back.
|
|
70
69
|
*/
|
|
71
70
|
export function osc8Sequences(text) {
|
|
72
|
-
return [...text.matchAll(
|
|
71
|
+
return [...text.matchAll(new RegExp(OSC8.source, "g"))].map((m) => ({
|
|
73
72
|
index: m.index,
|
|
74
73
|
length: m[0].length,
|
|
75
74
|
params: m[1],
|
package/dist/core/paint.d.ts
CHANGED
|
@@ -71,7 +71,8 @@ export declare class SurfacePainter implements Painter {
|
|
|
71
71
|
* Paint `frame` over the last frame, leaving the cursor on its last row,
|
|
72
72
|
* and return it as painted. No row is wider than the screen, since one that
|
|
73
73
|
* soft-wrapped would push every row below it down a row the next paint does
|
|
74
|
-
* not go back over.
|
|
74
|
+
* not go back over. The rows returned are what `destination` shows
|
|
75
|
+
* (`shownOn`): under reduced motion, nothing in them blinks.
|
|
75
76
|
*/
|
|
76
77
|
paint(frame: FrameSource, screen: Screen, destination: Destination): Segment[][];
|
|
77
78
|
/**
|
package/dist/core/paint.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* the last row, and the newline that ends it is written once, when the frame
|
|
14
14
|
* is handed back.
|
|
15
15
|
*/
|
|
16
|
-
import { segmentsToString } from "./render.js";
|
|
16
|
+
import { segmentsToString, shownOn } from "./render.js";
|
|
17
17
|
import { Segment } from "./segment.js";
|
|
18
18
|
const GEOMETRY = {
|
|
19
19
|
alternate: {
|
|
@@ -84,10 +84,11 @@ export class SurfacePainter {
|
|
|
84
84
|
* Paint `frame` over the last frame, leaving the cursor on its last row,
|
|
85
85
|
* and return it as painted. No row is wider than the screen, since one that
|
|
86
86
|
* soft-wrapped would push every row below it down a row the next paint does
|
|
87
|
-
* not go back over.
|
|
87
|
+
* not go back over. The rows returned are what `destination` shows
|
|
88
|
+
* (`shownOn`): under reduced motion, nothing in them blinks.
|
|
88
89
|
*/
|
|
89
90
|
paint(frame, screen, destination) {
|
|
90
|
-
const rows = fitRows(frame(), screen);
|
|
91
|
+
const rows = fitRows(frame(), screen).map((row) => row.map((segment) => shownOn(segment, destination)));
|
|
91
92
|
this.write(SYNC_START + this.over(rows, screen, destination) + SYNC_END);
|
|
92
93
|
return rows;
|
|
93
94
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pattern — `Pattern`: a regular expression held where every caller reaches
|
|
3
|
+
* it — module scope, a class static, a renderable's field — with no cursor
|
|
4
|
+
* for them to share.
|
|
5
|
+
*
|
|
6
|
+
* A `RegExp` carries `lastIndex`, and the `exec`, `test` and `replace` of a
|
|
7
|
+
* global or sticky one write it, so a global regex held at module scope is
|
|
8
|
+
* state that every caller moves. A regex with neither flag has a `lastIndex`
|
|
9
|
+
* that `exec`, `test`, `match`, `replace` and `split` never write. `pattern`
|
|
10
|
+
* is where that is checked: it refuses `g` and `y`, and hands back only
|
|
11
|
+
* those, with `source` and `flags` to compose it into another. A cursor — a
|
|
12
|
+
* sticky scan, a global replace — is made in the function that runs it, so
|
|
13
|
+
* each call owns its own.
|
|
14
|
+
*/
|
|
15
|
+
declare const PATTERN: unique symbol;
|
|
16
|
+
/** A regex with no cursor: only `pattern` makes one. */
|
|
17
|
+
export type Pattern = Pick<RegExp, "exec" | "test" | "source" | "flags" | typeof Symbol.match | typeof Symbol.replace | typeof Symbol.split> & {
|
|
18
|
+
readonly [PATTERN]: true;
|
|
19
|
+
};
|
|
20
|
+
export declare function pattern(re: RegExp): Pattern;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pattern — `Pattern`: a regular expression held where every caller reaches
|
|
3
|
+
* it — module scope, a class static, a renderable's field — with no cursor
|
|
4
|
+
* for them to share.
|
|
5
|
+
*
|
|
6
|
+
* A `RegExp` carries `lastIndex`, and the `exec`, `test` and `replace` of a
|
|
7
|
+
* global or sticky one write it, so a global regex held at module scope is
|
|
8
|
+
* state that every caller moves. A regex with neither flag has a `lastIndex`
|
|
9
|
+
* that `exec`, `test`, `match`, `replace` and `split` never write. `pattern`
|
|
10
|
+
* is where that is checked: it refuses `g` and `y`, and hands back only
|
|
11
|
+
* those, with `source` and `flags` to compose it into another. A cursor — a
|
|
12
|
+
* sticky scan, a global replace — is made in the function that runs it, so
|
|
13
|
+
* each call owns its own.
|
|
14
|
+
*/
|
|
15
|
+
export function pattern(re) {
|
|
16
|
+
// [LAW:no-silent-failure] A held cursor is refused where it is made, not found later as a match that began mid-string.
|
|
17
|
+
if (re.global || re.sticky) {
|
|
18
|
+
throw new TypeError(`/${re.source}/${re.flags} keeps a cursor in lastIndex; make it in the function that runs it`);
|
|
19
|
+
}
|
|
20
|
+
return re;
|
|
21
|
+
}
|
package/dist/core/place.js
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
import { Segment } from "./segment.js";
|
|
21
21
|
import { Measurement } from "./measure.js";
|
|
22
|
+
import { render } from "./protocol.js";
|
|
22
23
|
// The share of the spare cells that goes on the left; the rest go on the right.
|
|
23
24
|
// Right-alignment pads no right side at all, which is the reference's choice
|
|
24
25
|
// and not a zero: a line that ends at the edge carries no trailing blanks.
|
|
@@ -39,7 +40,7 @@ export function placeBlock(renderable, align, options) {
|
|
|
39
40
|
// (`Measurement.get` answers for it), and the block is then only as wide as
|
|
40
41
|
// what it actually drew.
|
|
41
42
|
const width = Measurement.get(options, renderable).maximum;
|
|
42
|
-
const drawn = Segment.splitLines(
|
|
43
|
+
const drawn = Segment.splitLines(render(renderable, { ...options, maxWidth: width, height: undefined }));
|
|
43
44
|
const [blockWidth, height] = Segment.getShape(drawn);
|
|
44
45
|
const [left, right] = PADS[align](Math.max(0, options.maxWidth - blockWidth));
|
|
45
46
|
return Segment.setShape(drawn, blockWidth, height).map((line) => [...pad(left), ...line, ...pad(right)]);
|
package/dist/core/pretty.js
CHANGED
|
@@ -18,10 +18,12 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { asCellCol, cellColToCodeUnitOffset, cellLen, graphemes, splitAtCells } from "./cells.js";
|
|
20
20
|
import { divideLine } from "./wrap.js";
|
|
21
|
+
import { Memo } from "./memo.js";
|
|
21
22
|
import { Segment } from "./segment.js";
|
|
22
23
|
import { RichText, stripControlChars } from "./text.js";
|
|
23
24
|
import { ReprHighlighter } from "./highlighter.js";
|
|
24
|
-
import { drawable } from "./protocol.js";
|
|
25
|
+
import { drawable, render } from "./protocol.js";
|
|
26
|
+
import { pattern } from "./pattern.js";
|
|
25
27
|
const reprHighlighter = new ReprHighlighter();
|
|
26
28
|
/**
|
|
27
29
|
* What a value is bounded by when whoever formats it has not seen it:
|
|
@@ -453,7 +455,7 @@ const elided = (dropped) => dropped > 0 ? [{ head: `... +${dropped}`, join: "",
|
|
|
453
455
|
* An index is at most 15 digits: every such literal is a safe integer and
|
|
454
456
|
* names itself, where `99999999999999999999` would name `1e20`'s key.
|
|
455
457
|
*/
|
|
456
|
-
const BARE_KEY = /^(?![^]*\p{Default_Ignorable_Code_Point})(?:[\p{ID_Start}$_][\p{ID_Continue}$]*|0|[1-9]\d{0,14})$/u;
|
|
458
|
+
const BARE_KEY = pattern(/^(?![^]*\p{Default_Ignorable_Code_Point})(?:[\p{ID_Start}$_][\p{ID_Continue}$]*|0|[1-9]\d{0,14})$/u);
|
|
457
459
|
/**
|
|
458
460
|
* What Python's `str.isprintable` refuses \u2014 control, format, private-use,
|
|
459
461
|
* unassigned, and every separator but the space \u2014 which Rich's repr escapes
|
|
@@ -461,9 +463,9 @@ const BARE_KEY = /^(?![^]*\p{Default_Ignorable_Code_Point})(?:[\p{ID_Start}$_][\
|
|
|
461
463
|
* byte reaches the terminal as a control, and a format character hides or
|
|
462
464
|
* reorders what is around it.
|
|
463
465
|
*/
|
|
464
|
-
const
|
|
466
|
+
const unprintable = () => /(?! )[\p{Cc}\p{Cf}\p{Co}\p{Cn}\p{Zl}\p{Zp}\p{Zs}]/gu;
|
|
465
467
|
/** `value` in double quotes, every character that does not print escaped. */
|
|
466
|
-
const quoted = (value) => JSON.stringify(value).replace(
|
|
468
|
+
const quoted = (value) => JSON.stringify(value).replace(unprintable(), (c) => {
|
|
467
469
|
const hex = c.codePointAt(0).toString(16).padStart(4, "0");
|
|
468
470
|
return hex.length > 4 ? `\\u{${hex}}` : `\\u${hex}`;
|
|
469
471
|
});
|
|
@@ -477,7 +479,7 @@ export class Pretty {
|
|
|
477
479
|
indentGuides;
|
|
478
480
|
highlighter;
|
|
479
481
|
// [LAW:no-shared-mutable-globals] A private memo, written only by `_cutString`.
|
|
480
|
-
cutStrings = new
|
|
482
|
+
cutStrings = new Memo();
|
|
481
483
|
constructor(data, options) {
|
|
482
484
|
this.data = data;
|
|
483
485
|
this.indent = options?.indent ?? 4;
|
|
@@ -491,7 +493,7 @@ export class Pretty {
|
|
|
491
493
|
*render(options) {
|
|
492
494
|
// `toText` has no `end`, for callers that set it inside a line; rendered,
|
|
493
495
|
// a `Pretty` is a block of its own, as the reference's is.
|
|
494
|
-
yield* this.toText(options)
|
|
496
|
+
yield* render(this.toText(options), options);
|
|
495
497
|
yield Segment.line();
|
|
496
498
|
}
|
|
497
499
|
/** The value laid out for `options.maxWidth` and highlighted: the text this renders. */
|
|
@@ -595,15 +597,12 @@ export class Pretty {
|
|
|
595
597
|
* memoised per value.
|
|
596
598
|
*/
|
|
597
599
|
_cutString(value, max) {
|
|
598
|
-
|
|
599
|
-
if (cut === undefined) {
|
|
600
|
+
return this.cutStrings.get(value, () => {
|
|
600
601
|
const clusters = graphemes(value);
|
|
601
|
-
|
|
602
|
+
return clusters.length <= max
|
|
602
603
|
? quoted(value)
|
|
603
604
|
: quoted(clusters.slice(0, max).join("")) + `+${clusters.length - max}`;
|
|
604
|
-
|
|
605
|
-
}
|
|
606
|
-
return cut;
|
|
605
|
+
});
|
|
607
606
|
}
|
|
608
607
|
/**
|
|
609
608
|
* A container, or the text standing in for one that is empty or past the
|
package/dist/core/protocol.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* [LAW:one-source-of-truth] These interfaces are the single authority for the rendering contract.
|
|
4
4
|
*/
|
|
5
5
|
import type { Segment } from "./segment.js";
|
|
6
|
-
import { type
|
|
6
|
+
import { Style, type Hold, type StyleSyntaxError, type Theme } from "./style.js";
|
|
7
7
|
import { ColorDepth } from "./color.js";
|
|
8
8
|
import type { Highlighter } from "./highlighter.js";
|
|
9
9
|
/**
|
|
@@ -17,6 +17,15 @@ import type { Highlighter } from "./highlighter.js";
|
|
|
17
17
|
* wrapping and leaves the edge, so a line too wide is cut by the method here.
|
|
18
18
|
*/
|
|
19
19
|
export type OverflowMethod = "fold" | "crop" | "ellipsis" | "ignore";
|
|
20
|
+
/**
|
|
21
|
+
* What draws frames — a `Live`, an `App` — as what draws in them sees it:
|
|
22
|
+
* the time a frame drawn now is drawn for, the host's clock read through its
|
|
23
|
+
* timeline for a view on it (`frameTime`, `./view.ts`). Not a `Clock`: under
|
|
24
|
+
* a paused timeline it holds, and under a reversed one it runs backwards.
|
|
25
|
+
*/
|
|
26
|
+
export interface FrameHost {
|
|
27
|
+
readonly frameTime: number;
|
|
28
|
+
}
|
|
20
29
|
export interface RenderOptions {
|
|
21
30
|
/**
|
|
22
31
|
* The cells this renderable may occupy. A count of cells, so a non-negative
|
|
@@ -68,8 +77,8 @@ export interface RenderOptions {
|
|
|
68
77
|
highlighter?: Highlighter;
|
|
69
78
|
/**
|
|
70
79
|
* The depth the output will be encoded at, `null` when it carries no colour.
|
|
71
|
-
* A renderable
|
|
72
|
-
*
|
|
80
|
+
* A renderable that measures what it draws — the strip's joiner, holding a
|
|
81
|
+
* seam's ink off its ground — measures the colours the terminal will draw at
|
|
73
82
|
* this depth, which at 256 colours or fewer are not the colours it was
|
|
74
83
|
* handed. Absent means truecolor.
|
|
75
84
|
*/
|
|
@@ -87,15 +96,56 @@ export interface RenderOptions {
|
|
|
87
96
|
*/
|
|
88
97
|
onStyleError?: StyleErrorHandler;
|
|
89
98
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
99
|
+
* The reader asked for reduced motion — CSS's `prefers-reduced-motion`,
|
|
100
|
+
* which a terminal has no way to report, so a host is told. A renderable
|
|
101
|
+
* built for the time the host draws at draws every animation reduced, its
|
|
102
|
+
* motion taken out and its content kept on time (`shownAt`,
|
|
103
|
+
* `./view.ts`; `Animation.reduced`, `./animation.ts`). Absent,
|
|
104
|
+
* everything moves. Nothing here reads it from the environment.
|
|
105
|
+
*/
|
|
106
|
+
reducedMotion?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* The frame being drawn: `time`, the moment it is drawn for, in seconds, on
|
|
109
|
+
* the clock its cells' `nextChange` stamps are read on, and `host`, the
|
|
110
|
+
* host drawing it, whose `frameTime` that moment was. It is how a
|
|
111
|
+
* renderable that lives across frames — a widget, a `Progress` — draws for
|
|
112
|
+
* the time without being rebuilt each frame with one, and without reading
|
|
113
|
+
* a clock. Absent, the frame is drawn for no moment — a `print` — and
|
|
114
|
+
* nothing drawn from it moves.
|
|
115
|
+
*/
|
|
116
|
+
frame?: {
|
|
117
|
+
readonly time: number;
|
|
118
|
+
readonly host: FrameHost;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Told of every renderable `render` is asked for, as it is asked, so the
|
|
122
|
+
* calls arrive in document order: a container before what it holds, what
|
|
123
|
+
* it holds in the order it renders it. `"drawn"` is a renderable drawn at
|
|
124
|
+
* the width it was handed; `"held"` is one handed no column, which is still
|
|
125
|
+
* in the view but has nothing drawn for it (`render`). A renderable rendered
|
|
126
|
+
* twice is told twice. A render made to measure is not drawing and is not
|
|
127
|
+
* told (`measuring`).
|
|
96
128
|
*/
|
|
97
|
-
|
|
129
|
+
onPresent?: (renderable: Renderable, presence: Presence) => void;
|
|
130
|
+
/**
|
|
131
|
+
* Told of a hold the frame is in that no cell of it may carry: an animation
|
|
132
|
+
* placed in the view reports its own, whether or not it drew a cell — one
|
|
133
|
+
* not yet entered draws none — and one a container crops away is still
|
|
134
|
+
* reported. It reaches whatever `frame` reaches, so a container that hands
|
|
135
|
+
* its child the frame's time hands back the child's hold with no word about
|
|
136
|
+
* either. [LAW:composability] Absent, nobody is listening. A measurement
|
|
137
|
+
* (`measuring`) and a held render (`holding`) tell too: what they find
|
|
138
|
+
* decides the frame's layout, so when it changes, the frame may.
|
|
139
|
+
*/
|
|
140
|
+
onHold?: (hold: Hold) => void;
|
|
98
141
|
}
|
|
142
|
+
/** The one field of the render options that says whether the reader wants motion. */
|
|
143
|
+
export type Motion = Pick<RenderOptions, "reducedMotion">;
|
|
144
|
+
/**
|
|
145
|
+
* Whether a renderable the view holds was drawn, or held: in the view, handed
|
|
146
|
+
* no column, and so not drawn (`render`).
|
|
147
|
+
*/
|
|
148
|
+
export type Presence = "drawn" | "held";
|
|
99
149
|
/** Whether `text` is all ASCII — what an `asciiOnly` output can draw. */
|
|
100
150
|
export declare const isAscii: (text: string) => boolean;
|
|
101
151
|
/**
|
|
@@ -210,7 +260,10 @@ export declare function getStyle(options: RenderOptions, style: string | Style):
|
|
|
210
260
|
* every bundled theme. So where the depth would turn a fixed colour of the
|
|
211
261
|
* pair into a slot, the pair is dropped and the run is drawn on the
|
|
212
262
|
* terminal's own foreground and background, which its theme does make
|
|
213
|
-
* readable; its attributes still set it apart.
|
|
263
|
+
* readable; its attributes still set it apart. Both are named, not left
|
|
264
|
+
* unset, so the colour of whatever the run sits in — a quote, a link — does
|
|
265
|
+
* not show through: Rich's code keeps its own colours inside a quote, and the
|
|
266
|
+
* terminal's are the ones it keeps here. A style whose colours are
|
|
214
267
|
* slots already (`white on blue`), or that paints no ground (`bold magenta`),
|
|
215
268
|
* was written for the terminal's own colours and is drawn as written. Rich
|
|
216
269
|
* draws a highlighted line number the same way below 256 colours
|
|
@@ -238,6 +291,78 @@ export declare function groundedStyle(options: RenderOptions, style: Style): Sty
|
|
|
238
291
|
* ignored the request and emitted its full natural width.
|
|
239
292
|
*/
|
|
240
293
|
export declare function withCellWidth(options: RenderOptions): RenderOptions;
|
|
294
|
+
/** Under one column there is nothing to draw, or to measure. */
|
|
295
|
+
export declare function drawsNothing(options: {
|
|
296
|
+
readonly maxWidth: number;
|
|
297
|
+
}): boolean;
|
|
298
|
+
/**
|
|
299
|
+
* One render pass: the outermost `render` or `measure` call — a host's frame,
|
|
300
|
+
* a print — and every `next()` of what it returned, at any depth. Opaque: it
|
|
301
|
+
* is only an identity, which a `State` compares to say whether this pass made
|
|
302
|
+
* it.
|
|
303
|
+
*/
|
|
304
|
+
export interface Pass {
|
|
305
|
+
readonly __pass: unique symbol;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* `handler` run as if between passes: a callback a render makes to user code to
|
|
309
|
+
* report something it met, such as `onStyleError`, is an event handler, and may
|
|
310
|
+
* write what one may — print to a console, set a `State` — as React lets an
|
|
311
|
+
* event handler set state.
|
|
312
|
+
*/
|
|
313
|
+
export declare function betweenPasses<T>(handler: () => T): T;
|
|
314
|
+
/** The pass a render or measure in progress belongs to, or `undefined` between passes. */
|
|
315
|
+
export declare function activePass(): Pass | undefined;
|
|
316
|
+
/**
|
|
317
|
+
* `effect` run once the render pass in progress has drawn its last segment,
|
|
318
|
+
* between passes, where it may write what an event handler may: React's commit
|
|
319
|
+
* phase. A render that learns something only drawing can tell it — the lines
|
|
320
|
+
* content shown through a `Viewport` runs to at the width it was handed —
|
|
321
|
+
* draws from what it learned and hands the commit here, rather than writing it
|
|
322
|
+
* as it draws.
|
|
323
|
+
*
|
|
324
|
+
* Effects run in the order they were handed over, which is document order. A
|
|
325
|
+
* measurement commits nothing, and neither does a pass that throws or whose
|
|
326
|
+
* caller stops iterating it early: nobody saw what it drew. Outside a pass — a
|
|
327
|
+
* renderable's `render` called directly — there is nothing to wait for, and
|
|
328
|
+
* `effect` runs now.
|
|
329
|
+
*/
|
|
330
|
+
export declare function afterPass(effect: () => void): void;
|
|
331
|
+
/**
|
|
332
|
+
* `renderable` drawn under `options`: Rich's `Console.render`, which every
|
|
333
|
+
* renderable there is drawn through, so under one column nothing is.
|
|
334
|
+
*
|
|
335
|
+
* [LAW:single-enforcer] The one place that rule is kept. Every call of a
|
|
336
|
+
* `Renderable`'s `render` in `src/` goes through here — a container drawing
|
|
337
|
+
* its child, a renderable drawing the text it built, a host drawing a frame —
|
|
338
|
+
* and `test/seam/render-calls.test.ts` fails on one that does not. Before
|
|
339
|
+
* this, each container asked `drawsNothing` itself, and the ones that forgot
|
|
340
|
+
* drew a child handed no column anyway.
|
|
341
|
+
*
|
|
342
|
+
* It is where a render pass is entered (`Pass`), so it is the one place a
|
|
343
|
+
* write during render is refused at: a `State` set in a pass that did not make
|
|
344
|
+
* it throws (`./state.ts`).
|
|
345
|
+
*
|
|
346
|
+
* It is also the one reporter of what the view holds (`onPresent`). Under one
|
|
347
|
+
* column a renderable is held: in the view, with nothing of it on the frame.
|
|
348
|
+
* It is drawn all the same and what it drew dropped (`holding`), so what a held
|
|
349
|
+
* container is reported holding is what it draws, under the options it hands
|
|
350
|
+
* each child — one description of a container's traversal, not a second
|
|
351
|
+
* kept beside it.
|
|
352
|
+
*/
|
|
353
|
+
export declare function render(renderable: Renderable, options: RenderOptions): Iterable<Segment>;
|
|
354
|
+
/**
|
|
355
|
+
* What `measurable` reports under `options`: asked in a render pass, as
|
|
356
|
+
* `render` draws in one, with `measuring`'s options.
|
|
357
|
+
*
|
|
358
|
+
* [LAW:single-enforcer] Every call of a `Measurable`'s `measure` in `src/`
|
|
359
|
+
* goes through here, as every `render` goes through `render`;
|
|
360
|
+
* `test/seam/render-calls.test.ts` holds both.
|
|
361
|
+
*/
|
|
362
|
+
export declare function measure(measurable: Measurable, options: RenderOptions): {
|
|
363
|
+
minimum: number;
|
|
364
|
+
maximum: number;
|
|
365
|
+
};
|
|
241
366
|
/**
|
|
242
367
|
* The options a renderable should *lay out against*: `withCellWidth`, with an
|
|
243
368
|
* unbounded offer resolved to the renderable's own natural width.
|
|
@@ -273,16 +398,6 @@ export declare function withCellWidth(options: RenderOptions): RenderOptions;
|
|
|
273
398
|
* rather than zero, and saying so names the cause — where `String.repeat` and
|
|
274
399
|
* `new Array` only ever name their own argument.
|
|
275
400
|
*/
|
|
276
|
-
/**
|
|
277
|
-
* `options` as a measurement is asked with. A `measure` that renders to learn
|
|
278
|
-
* its shape draws nothing on the frame, so it reports no owner to `onDraw` —
|
|
279
|
-
* one that did would put a widget in document order at the moment a
|
|
280
|
-
* container measured it, and keep one the frame then cropped away.
|
|
281
|
-
*
|
|
282
|
-
* [LAW:single-enforcer] Every measurement starts here: `Measurement.get` and
|
|
283
|
-
* `withBoundedWidth` ask through it, and each `measure` passes it on.
|
|
284
|
-
*/
|
|
285
|
-
export declare function measuring(options: RenderOptions): RenderOptions;
|
|
286
401
|
export declare function withBoundedWidth(options: RenderOptions, self: Measurable): RenderOptions;
|
|
287
402
|
export interface Renderable {
|
|
288
403
|
render(options: RenderOptions): Iterable<Segment>;
|