@promptctl/rich-js 0.18.1 → 0.19.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 +9 -7
- package/dist/core/box.d.ts +3 -1
- package/dist/core/box.js +6 -13
- package/dist/core/cells.d.ts +61 -28
- package/dist/core/cells.js +171 -124
- package/dist/core/clock.d.ts +48 -0
- package/dist/core/clock.js +42 -0
- package/dist/core/color.d.ts +98 -18
- package/dist/core/color.js +331 -144
- package/dist/core/console.d.ts +38 -7
- package/dist/core/console.js +159 -90
- package/dist/core/easing.d.ts +86 -0
- package/dist/core/easing.js +171 -0
- package/dist/core/env.d.ts +16 -0
- package/dist/core/env.js +16 -0
- package/dist/core/export-html.js +1 -4
- package/dist/core/export-lines.d.ts +22 -13
- package/dist/core/export-lines.js +37 -19
- package/dist/core/export-svg.d.ts +49 -0
- package/dist/core/export-svg.js +213 -0
- package/dist/core/fnv1a.d.ts +10 -0
- package/dist/core/fnv1a.js +17 -0
- package/dist/core/highlighter.d.ts +2 -2
- package/dist/core/highlighter.js +113 -47
- package/dist/core/json.js +1 -1
- package/dist/core/markup.d.ts +28 -7
- package/dist/core/markup.js +235 -312
- package/dist/core/measure.d.ts +3 -3
- package/dist/core/measure.js +12 -7
- package/dist/core/memo.d.ts +19 -0
- package/dist/core/memo.js +34 -0
- package/dist/core/osc8.d.ts +6 -6
- package/dist/core/osc8.js +9 -21
- package/dist/core/paint.d.ts +107 -0
- package/dist/core/paint.js +150 -0
- package/dist/core/place.d.ts +1 -1
- package/dist/core/place.js +4 -6
- package/dist/core/pretty.d.ts +105 -2
- package/dist/core/pretty.js +527 -97
- package/dist/core/protocol.d.ts +41 -3
- package/dist/core/protocol.js +20 -0
- package/dist/core/render.d.ts +33 -30
- package/dist/core/render.js +43 -83
- package/dist/core/segment.d.ts +6 -5
- package/dist/core/segment.js +11 -15
- package/dist/core/strip.d.ts +13 -2
- package/dist/core/strip.js +44 -23
- package/dist/core/style.d.ts +27 -7
- package/dist/core/style.js +97 -34
- package/dist/core/text.d.ts +43 -16
- package/dist/core/text.js +180 -59
- package/dist/core/wrap.d.ts +5 -0
- package/dist/core/wrap.js +16 -3
- package/dist/host/app.d.ts +31 -19
- package/dist/host/app.js +90 -60
- package/dist/host/index.d.ts +2 -1
- package/dist/host/terminal-host.d.ts +3 -2
- package/dist/index.d.ts +17 -10
- package/dist/index.js +11 -4
- package/dist/node/prompt.d.ts +13 -0
- package/dist/node/prompt.js +30 -9
- package/dist/node/save.d.ts +4 -3
- package/dist/node/save.js +6 -3
- package/dist/node/terminal-host.d.ts +3 -2
- package/dist/node/traceback.d.ts +2 -1
- package/dist/node/traceback.js +3 -39
- package/dist/renderables/align.js +2 -9
- package/dist/renderables/columns.d.ts +45 -29
- package/dist/renderables/columns.js +142 -103
- package/dist/renderables/constrain.js +6 -12
- package/dist/renderables/effect.d.ts +98 -0
- package/dist/renderables/effect.js +160 -0
- package/dist/renderables/embed.d.ts +87 -30
- package/dist/renderables/embed.js +134 -45
- package/dist/renderables/group.d.ts +6 -3
- package/dist/renderables/group.js +5 -0
- package/dist/renderables/layout.d.ts +6 -23
- package/dist/renderables/layout.js +24 -113
- package/dist/renderables/live.d.ts +40 -16
- package/dist/renderables/live.js +96 -83
- package/dist/renderables/markdown.d.ts +16 -2
- package/dist/renderables/markdown.js +521 -118
- package/dist/renderables/padding.d.ts +22 -1
- package/dist/renderables/padding.js +30 -24
- package/dist/renderables/panel.d.ts +31 -33
- package/dist/renderables/panel.js +137 -141
- package/dist/renderables/progress.d.ts +104 -16
- package/dist/renderables/progress.js +205 -81
- package/dist/renderables/progressBar.d.ts +2 -2
- package/dist/renderables/progressBar.js +30 -19
- package/dist/renderables/prompt.d.ts +37 -15
- package/dist/renderables/prompt.js +125 -85
- package/dist/renderables/ratio.d.ts +123 -0
- package/dist/renderables/ratio.js +213 -0
- package/dist/renderables/rule.d.ts +1 -0
- package/dist/renderables/rule.js +44 -48
- package/dist/renderables/spinner.d.ts +28 -2
- package/dist/renderables/spinner.js +52 -19
- package/dist/renderables/status.d.ts +13 -7
- package/dist/renderables/status.js +15 -29
- package/dist/renderables/syntax.d.ts +37 -7
- package/dist/renderables/syntax.js +134 -83
- package/dist/renderables/table.d.ts +58 -20
- package/dist/renderables/table.js +370 -192
- package/dist/renderables/traceback.d.ts +5 -4
- package/dist/renderables/traceback.js +239 -68
- package/dist/renderables/tree.d.ts +10 -2
- package/dist/renderables/tree.js +61 -34
- package/dist/renderables/viewport.js +2 -4
- package/dist/template-bindings/color-funcs.d.ts +31 -9
- package/dist/template-bindings/color-funcs.js +40 -14
- package/dist/template-bindings/helpers.d.ts +4 -2
- package/dist/template-bindings/helpers.js +5 -20
- package/dist/template-bindings/index.d.ts +29 -17
- package/dist/template-bindings/index.js +36 -20
- package/dist/template-bindings/palette-funcs.d.ts +3 -1
- package/dist/template-bindings/palette-funcs.js +11 -7
- package/dist/template-bindings/style-funcs.js +4 -2
- package/dist/themes/buildPalette.d.ts +24 -3
- package/dist/themes/buildPalette.js +52 -8
- package/dist/themes/colorMath.d.ts +29 -17
- package/dist/themes/colorMath.js +74 -48
- package/dist/themes/colorRef.d.ts +2 -17
- package/dist/themes/colorRef.js +13 -31
- package/dist/themes/palette.d.ts +24 -0
- package/dist/themes/palette.js +46 -3
- package/dist/themes/ramp.d.ts +21 -34
- package/dist/themes/ramp.js +23 -42
- package/dist/themes/registry.js +39 -28
- package/dist/widgets/button.d.ts +2 -6
- package/dist/widgets/button.js +9 -40
- package/dist/widgets/checkbox.d.ts +2 -5
- package/dist/widgets/checkbox.js +9 -31
- package/dist/widgets/dropdown.d.ts +2 -5
- package/dist/widgets/dropdown.js +14 -48
- package/dist/widgets/ink.d.ts +22 -0
- package/dist/widgets/ink.js +31 -0
- package/dist/widgets/slider.d.ts +2 -5
- package/dist/widgets/slider.js +11 -34
- package/dist/widgets/text-input.d.ts +19 -10
- package/dist/widgets/text-input.js +156 -147
- package/dist/widgets/themed-widget.d.ts +20 -0
- package/dist/widgets/themed-widget.js +89 -0
- package/dist/widgets/toggle.d.ts +2 -5
- package/dist/widgets/toggle.js +8 -31
- package/dist/widgets/widget-app.d.ts +2 -0
- package/dist/widgets/widget-app.js +13 -6
- package/dist/widgets/widget-base.d.ts +2 -0
- package/dist/widgets/widget-base.js +9 -2
- package/package.json +11 -1
|
@@ -1,34 +1,64 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Syntax — renders source code with basic syntax highlighting.
|
|
3
3
|
* Uses built-in tokenization (no external dependency).
|
|
4
|
+
*
|
|
5
|
+
* Colours are names in the console's theme (`syntax.keyword`,
|
|
6
|
+
* `syntax.line_number`, …), not a per-instance palette: a theme is how every
|
|
7
|
+
* other renderable here is restyled, and a second styling vocabulary on this
|
|
8
|
+
* one class would be a second answer to "what colour is a keyword".
|
|
4
9
|
*/
|
|
5
|
-
import { cellLen } from "../core/cells.js";
|
|
10
|
+
import { cellLen, expandTabs, parseTabSize } from "../core/cells.js";
|
|
6
11
|
import { Segment } from "../core/segment.js";
|
|
7
|
-
import { Style } from "../core/style.js";
|
|
8
12
|
import { RichText } from "../core/text.js";
|
|
9
|
-
import { drawable } from "../core/protocol.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
"
|
|
29
|
-
"string"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
13
|
+
import { drawable, groundedStyle, getStyle, withBoundedWidth, withCellWidth, } from "../core/protocol.js";
|
|
14
|
+
/**
|
|
15
|
+
* One regex per grammar, each token a named alternative. A single left-to-right
|
|
16
|
+
* scan is what keeps a `//` inside a string from starting a comment, and a
|
|
17
|
+
* keyword inside a comment from being drawn as one: at any position the
|
|
18
|
+
* leftmost match wins, and among matches starting there the earliest rule.
|
|
19
|
+
* `(?!)` never matches, so a grammar with no rules is still a regex.
|
|
20
|
+
*/
|
|
21
|
+
function grammar(rules) {
|
|
22
|
+
return new RegExp([...rules.map(([token, source]) => `(?<${token}>${source})`), "(?!)"].join("|"), "g");
|
|
23
|
+
}
|
|
24
|
+
// Not after a `.`: `map.get` and `node.type` are properties, not keywords.
|
|
25
|
+
const words = (list) => `(?<!\\.)\\b(?:${list.split(" ").join("|")})\\b`;
|
|
26
|
+
const NUMBER = String.raw `\b(?:0x[0-9a-fA-F]+|\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b`;
|
|
27
|
+
const QUOTED = String.raw `"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'`;
|
|
28
|
+
const JS_KEYWORDS = "function class const let var return if else for while do switch case break continue new throw try catch " +
|
|
29
|
+
"finally import export from default async await yield of in typeof instanceof void delete this super extends static";
|
|
30
|
+
const TS_KEYWORDS = "interface type enum implements private public protected readonly as declare namespace keyof satisfies abstract is infer";
|
|
31
|
+
const JAVASCRIPT = [
|
|
32
|
+
["comment", String.raw `\/\/[^\n]*|\/\*[\s\S]*?\*\/`],
|
|
33
|
+
["string", String.raw `${QUOTED}|` + "`(?:[^`\\\\]|\\\\.)*`"],
|
|
34
|
+
["constant", words("true false null undefined NaN Infinity")],
|
|
35
|
+
["keyword", words(JS_KEYWORDS)],
|
|
36
|
+
["number", NUMBER],
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* [LAW:one-type-per-behavior] A language is a value here — a grammar — not a
|
|
40
|
+
* code path. The union is the set of languages this module can actually
|
|
41
|
+
* tokenize, so a name it cannot is a compile error rather than a silent plain
|
|
42
|
+
* render; `"text"` is the grammar with no rules.
|
|
43
|
+
*/
|
|
44
|
+
const GRAMMARS = {
|
|
45
|
+
javascript: grammar(JAVASCRIPT),
|
|
46
|
+
typescript: grammar(JAVASCRIPT.map(([token, source]) => token === "keyword" ? [token, words(`${JS_KEYWORDS} ${TS_KEYWORDS}`)] : [token, source])),
|
|
47
|
+
python: grammar([
|
|
48
|
+
["comment", "#[^\\n]*"],
|
|
49
|
+
["string", String.raw `"""[\s\S]*?"""|'''[\s\S]*?'''|${QUOTED}`],
|
|
50
|
+
["constant", words("True False None")],
|
|
51
|
+
["keyword", words("def class return if elif else for while in not and or is import from as with try except finally raise " +
|
|
52
|
+
"pass break continue lambda yield global nonlocal assert del async await self cls")],
|
|
53
|
+
["number", NUMBER],
|
|
54
|
+
]),
|
|
55
|
+
bash: grammar([
|
|
56
|
+
["comment", "(?<![^\\s;])#[^\\n]*"],
|
|
57
|
+
["string", QUOTED],
|
|
58
|
+
["keyword", words("if then else elif fi for while until do done case esac function in return local export select")],
|
|
59
|
+
["number", NUMBER],
|
|
60
|
+
]),
|
|
61
|
+
text: grammar([]),
|
|
32
62
|
};
|
|
33
63
|
export class Syntax {
|
|
34
64
|
code;
|
|
@@ -39,77 +69,98 @@ export class Syntax {
|
|
|
39
69
|
highlightLines;
|
|
40
70
|
wordWrap;
|
|
41
71
|
tabSize;
|
|
42
|
-
|
|
72
|
+
/** The code with its tabs expanded, as lines — what both render and measure read. */
|
|
73
|
+
_lines;
|
|
74
|
+
constructor(code, language = "text", options) {
|
|
75
|
+
// A plain-JS caller, or one passing a language read at runtime, gets past
|
|
76
|
+
// the type; left here, the name surfaces at render as a TypeError about
|
|
77
|
+
// `undefined`. [LAW:no-silent-failure] Refused where it is given, by name.
|
|
78
|
+
if (!Object.hasOwn(GRAMMARS, language)) {
|
|
79
|
+
throw new TypeError(`Syntax has no grammar for ${JSON.stringify(language)}: use one of ${Object.keys(GRAMMARS).join(", ")}`);
|
|
80
|
+
}
|
|
43
81
|
this.code = code;
|
|
44
|
-
this.language = language
|
|
82
|
+
this.language = language;
|
|
45
83
|
this.lineNumbers = options?.lineNumbers ?? false;
|
|
46
84
|
this.startLine = options?.startLine ?? 1;
|
|
47
85
|
this.lineRange = options?.lineRange;
|
|
48
86
|
this.highlightLines = options?.highlightLines ?? new Set();
|
|
49
87
|
this.wordWrap = options?.wordWrap ?? false;
|
|
50
|
-
|
|
88
|
+
const tabSize = parseTabSize(options?.tabSize ?? 4);
|
|
89
|
+
this.tabSize = tabSize;
|
|
90
|
+
this._lines = expandTabs(code, tabSize).text.split("\n");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* The lines shown, as a 0-based half-open slice of `_lines`, and the number
|
|
94
|
+
* the first is given — render and measure both read them here, so a range
|
|
95
|
+
* counts the same in each. `lineRange` is 1-based and inclusive, and a line
|
|
96
|
+
* keeps the number it has in the whole code: `[3, 4]` shows lines 3 and 4
|
|
97
|
+
* numbered 3 and 4 (with a `startLine` of 1), as Rich does. A range reaching
|
|
98
|
+
* outside the code shows the part inside it, which may be none.
|
|
99
|
+
*/
|
|
100
|
+
_shown() {
|
|
101
|
+
const [start, end] = this.lineRange ?? [1, this._lines.length];
|
|
102
|
+
const from = Math.max(0, start - 1);
|
|
103
|
+
return { first: this.startLine + from, from, to: Math.max(from, end) };
|
|
104
|
+
}
|
|
105
|
+
/** Digits of the last number, a space, and the `│ ` rule; nothing without numbers. */
|
|
106
|
+
_gutterWidth(first, count) {
|
|
107
|
+
return this.lineNumbers ? String(first + count - 1).length + 3 : 0;
|
|
51
108
|
}
|
|
52
109
|
*render(options) {
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (this.lineRange) {
|
|
57
|
-
const [start, end] = this.lineRange;
|
|
58
|
-
lines = lines.slice(start - 1, end);
|
|
59
|
-
}
|
|
60
|
-
const lineNumWidth = this.lineNumbers
|
|
61
|
-
? String(this.startLine + lines.length - 1).length + 1
|
|
62
|
-
: 0;
|
|
63
|
-
// Tokenize the full text for highlighting
|
|
64
|
-
const text = new RichText(lines.join("\n"), { end: "" });
|
|
65
|
-
this._highlight(text);
|
|
66
|
-
const textLines = text.split("\n");
|
|
67
|
-
for (let i = 0; i < textLines.length; i++) {
|
|
68
|
-
const lineNo = this.startLine + i;
|
|
69
|
-
const isHighlighted = this.highlightLines.has(lineNo);
|
|
70
|
-
if (this.lineNumbers) {
|
|
71
|
-
const numStr = String(lineNo).padStart(lineNumWidth - 1) + " ";
|
|
72
|
-
const numStyle = isHighlighted
|
|
73
|
-
? Style.parse("bold on grey27")
|
|
74
|
-
: Style.parse("dim");
|
|
75
|
-
yield new Segment(numStr, numStyle);
|
|
76
|
-
yield new Segment(drawable(options, "│ ", "| "), Style.parse("dim"));
|
|
77
|
-
}
|
|
78
|
-
const line = textLines[i];
|
|
79
|
-
const segs = [...line.render({ ...options, maxWidth: options.maxWidth - lineNumWidth - 2 })];
|
|
80
|
-
// Filter out trailing newline from render
|
|
81
|
-
for (const seg of segs) {
|
|
82
|
-
if (seg.text !== "\n")
|
|
83
|
-
yield seg;
|
|
84
|
-
}
|
|
85
|
-
yield Segment.line();
|
|
86
|
-
}
|
|
110
|
+
const bounded = withBoundedWidth(options, this);
|
|
111
|
+
// A gutter wider than the offer is cut at its edge like any other row.
|
|
112
|
+
yield* Segment.cropLines(this._rows(bounded), bounded.maxWidth);
|
|
87
113
|
}
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
114
|
+
*_rows(options) {
|
|
115
|
+
const { first, from, to } = this._shown();
|
|
116
|
+
const numberStyle = getStyle(options, "syntax.line_number");
|
|
117
|
+
const highlightStyle = groundedStyle(options, getStyle(options, "syntax.line_number.highlight"));
|
|
118
|
+
const rule = drawable(options, "│ ", "| ");
|
|
119
|
+
// Tokenized whole and then sliced, so a block comment or a triple-quoted
|
|
120
|
+
// string that spans lines is one token even when the range starts inside it.
|
|
121
|
+
const text = new RichText(this._lines.join("\n"), { end: "" });
|
|
122
|
+
for (const match of text.plain.matchAll(GRAMMARS[this.language])) {
|
|
123
|
+
const [token] = Object.entries(match.groups).find(([, value]) => value !== undefined);
|
|
124
|
+
text.stylize(`syntax.${token}`, match.index, match.index + match[0].length);
|
|
93
125
|
}
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
126
|
+
const textLines = text.split("\n").slice(from, to);
|
|
127
|
+
const gutterWidth = this._gutterWidth(first, textLines.length);
|
|
128
|
+
// [LAW:dataflow-not-control-flow] `wordWrap` reaches the line as the
|
|
129
|
+
// overflow it is drawn with, not as a second path: wrapped, a line may
|
|
130
|
+
// become several rows; cropped, it is always one. Never justified: a
|
|
131
|
+
// caller's `justify` would align each line alone and lose its indent.
|
|
132
|
+
const lineOptions = {
|
|
133
|
+
...options,
|
|
134
|
+
maxWidth: Math.max(0, options.maxWidth - gutterWidth),
|
|
135
|
+
justify: undefined,
|
|
136
|
+
noWrap: !this.wordWrap,
|
|
137
|
+
overflow: this.wordWrap ? "fold" : "crop",
|
|
100
138
|
};
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
139
|
+
for (let i = 0; i < textLines.length; i++) {
|
|
140
|
+
const lineNo = first + i;
|
|
141
|
+
const style = this.highlightLines.has(lineNo) ? highlightStyle : numberStyle;
|
|
142
|
+
// Terminated, so an empty line is one empty row rather than none.
|
|
143
|
+
const rows = Segment.splitLines([...textLines[i].render(lineOptions), Segment.line()]);
|
|
144
|
+
for (let row = 0; row < rows.length; row++) {
|
|
145
|
+
if (this.lineNumbers) {
|
|
146
|
+
// A wrapped line's continuation rows keep the gutter, unnumbered.
|
|
147
|
+
const label = row === 0 ? String(lineNo) : "";
|
|
148
|
+
yield new Segment(label.padStart(gutterWidth - 3) + " ", style);
|
|
149
|
+
yield new Segment(rule, numberStyle);
|
|
150
|
+
}
|
|
151
|
+
yield* rows[row];
|
|
152
|
+
yield Segment.line();
|
|
108
153
|
}
|
|
109
154
|
}
|
|
110
155
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
156
|
+
/** The gutter is the narrowest it can be drawn; the widest shown line plus the gutter, the widest. */
|
|
157
|
+
measure(options) {
|
|
158
|
+
const { maxWidth } = withCellWidth(options);
|
|
159
|
+
const { first, from, to } = this._shown();
|
|
160
|
+
const lines = this._lines.slice(from, to);
|
|
161
|
+
const gutterWidth = this._gutterWidth(first, lines.length);
|
|
162
|
+
const widest = lines.reduce((width, line) => Math.max(width, cellLen(line)), 0);
|
|
163
|
+
const maximum = Math.min(gutterWidth + widest, maxWidth);
|
|
164
|
+
return { minimum: Math.min(gutterWidth, maximum), maximum };
|
|
114
165
|
}
|
|
115
166
|
}
|
|
@@ -8,8 +8,9 @@ import { RichText } from "../core/text.js";
|
|
|
8
8
|
import type { PaddingDimensions } from "./padding.js";
|
|
9
9
|
import type { Renderable, Measurable, OverflowMethod, RenderOptions } from "../core/protocol.js";
|
|
10
10
|
export interface ColumnOptions {
|
|
11
|
-
header
|
|
12
|
-
|
|
11
|
+
/** Anything a cell can hold, as Rich's `RenderableType` header is. */
|
|
12
|
+
header?: string | RichText | Renderable;
|
|
13
|
+
footer?: string | RichText | Renderable;
|
|
13
14
|
headerStyle?: string | Style;
|
|
14
15
|
footerStyle?: string | Style;
|
|
15
16
|
style?: string | Style;
|
|
@@ -20,6 +21,12 @@ export interface ColumnOptions {
|
|
|
20
21
|
ratio?: number;
|
|
21
22
|
noWrap?: boolean;
|
|
22
23
|
overflow?: OverflowMethod;
|
|
24
|
+
/**
|
|
25
|
+
* Whether the column's string cells — its header and footer among them — are
|
|
26
|
+
* drawn with the console's highlighter, as Rich's `Column(highlight=)`.
|
|
27
|
+
* `false` for a `Column` built alone; `addColumn` takes the table's.
|
|
28
|
+
*/
|
|
29
|
+
highlight?: boolean;
|
|
23
30
|
}
|
|
24
31
|
export declare class Column {
|
|
25
32
|
private _header;
|
|
@@ -34,15 +41,15 @@ export declare class Column {
|
|
|
34
41
|
ratio: number | undefined;
|
|
35
42
|
noWrap: boolean;
|
|
36
43
|
overflow: OverflowMethod;
|
|
44
|
+
highlight: boolean;
|
|
37
45
|
private _cells;
|
|
38
46
|
constructor(options?: ColumnOptions);
|
|
39
47
|
/**
|
|
40
|
-
* The two stamped cells,
|
|
48
|
+
* The two stamped cells, stamped on assignment rather than at the constructor.
|
|
41
49
|
* `Table.columns` hands out the live column and both fields are public, so a
|
|
42
50
|
* constructor-only stamp held only until the first `columns[0].footer = mine`
|
|
43
|
-
* — which installed content
|
|
44
|
-
*
|
|
45
|
-
* assumes `embeddedText` has been through. [LAW:parse-dont-validate] The setter
|
|
51
|
+
* — which installed content still owned by the caller into a slot every
|
|
52
|
+
* reader below assumes `embed` has been through. [LAW:parse-dont-validate] The setter
|
|
46
53
|
* is the border, so the guarantee holds for the object's whole lifetime and
|
|
47
54
|
* the constructor is one caller of it rather than the one place it is true.
|
|
48
55
|
*
|
|
@@ -51,13 +58,13 @@ export declare class Column {
|
|
|
51
58
|
* a column always has one and `show_footer` alone decides whether it is
|
|
52
59
|
* drawn. Modelling the absence as `undefined` instead made "no column has a
|
|
53
60
|
* footer" a state the render path could ask about — and it did, skipping the
|
|
54
|
-
* row a caller had asked for. `
|
|
61
|
+
* row a caller had asked for. `embed` already maps nothing onto empty,
|
|
55
62
|
* which is why the setters take `undefined` rather than defaulting around it.
|
|
56
63
|
*/
|
|
57
|
-
get header():
|
|
58
|
-
set header(content:
|
|
59
|
-
get footer():
|
|
60
|
-
set footer(content:
|
|
64
|
+
get header(): Renderable & Partial<Measurable>;
|
|
65
|
+
set header(content: ColumnOptions["header"]);
|
|
66
|
+
get footer(): Renderable & Partial<Measurable>;
|
|
67
|
+
set footer(content: ColumnOptions["footer"]);
|
|
61
68
|
get flexible(): boolean;
|
|
62
69
|
/** @internal */
|
|
63
70
|
addCell(cell: Renderable): void;
|
|
@@ -75,6 +82,8 @@ export interface TableOptions {
|
|
|
75
82
|
showLines?: boolean;
|
|
76
83
|
showEdge?: boolean;
|
|
77
84
|
padding?: PaddingDimensions;
|
|
85
|
+
collapsePadding?: boolean;
|
|
86
|
+
padEdge?: boolean;
|
|
78
87
|
style?: string | Style;
|
|
79
88
|
headerStyle?: string | Style;
|
|
80
89
|
footerStyle?: string | Style;
|
|
@@ -86,19 +95,23 @@ export interface TableOptions {
|
|
|
86
95
|
width?: number;
|
|
87
96
|
minWidth?: number;
|
|
88
97
|
rowStyles?: string[];
|
|
98
|
+
/** The `highlight` every column `addColumn` makes takes unless told otherwise (default: `false`). */
|
|
99
|
+
highlight?: boolean;
|
|
89
100
|
}
|
|
90
101
|
export declare class Table implements Renderable, Measurable {
|
|
91
102
|
private _columns;
|
|
92
103
|
private _rows;
|
|
93
104
|
readonly box: Box | null;
|
|
94
|
-
readonly
|
|
95
|
-
readonly
|
|
105
|
+
private readonly _title;
|
|
106
|
+
private readonly _caption;
|
|
96
107
|
readonly expand: boolean;
|
|
97
108
|
readonly showHeader: boolean;
|
|
98
109
|
readonly showFooter: boolean;
|
|
99
110
|
readonly showLines: boolean;
|
|
100
111
|
readonly showEdge: boolean;
|
|
101
112
|
readonly padding: [number, number, number, number];
|
|
113
|
+
readonly collapsePadding: boolean;
|
|
114
|
+
readonly padEdge: boolean;
|
|
102
115
|
readonly style: string | Style;
|
|
103
116
|
readonly headerStyle: string | Style;
|
|
104
117
|
readonly footerStyle: string | Style;
|
|
@@ -110,17 +123,20 @@ export declare class Table implements Renderable, Measurable {
|
|
|
110
123
|
readonly tableWidth: number | undefined;
|
|
111
124
|
readonly minWidth: number | undefined;
|
|
112
125
|
readonly rowStyles: string[];
|
|
126
|
+
readonly highlight: boolean;
|
|
127
|
+
get title(): (Renderable & Measurable) | undefined;
|
|
128
|
+
get caption(): (Renderable & Measurable) | undefined;
|
|
113
129
|
constructor(options?: TableOptions);
|
|
114
130
|
get columns(): Column[];
|
|
115
131
|
get rowCount(): number;
|
|
116
|
-
addColumn(header?:
|
|
132
|
+
addColumn(header?: ColumnOptions["header"], options?: ColumnOptions): this;
|
|
117
133
|
addRow(...cells: unknown[]): this;
|
|
118
134
|
addSection(): this;
|
|
119
135
|
render(rawOptions: RenderOptions): Iterable<Segment>;
|
|
120
136
|
/**
|
|
121
137
|
* [LAW:one-source-of-truth] Both ends of the range are widths the geometry
|
|
122
138
|
* actually produced — the maximum from the demands as they stand, the
|
|
123
|
-
* minimum from the same layout with every column asking for
|
|
139
|
+
* minimum from the same layout with every column asking for its minimum.
|
|
124
140
|
* Neither end stretches or fills into an offer: both only spend cells an
|
|
125
141
|
* offer happens to leave over, and a renderable reports the width its content
|
|
126
142
|
* wants rather than the width it was offered. A declared `width` is not an
|
|
@@ -137,6 +153,12 @@ export declare class Table implements Renderable, Measurable {
|
|
|
137
153
|
minimum: number;
|
|
138
154
|
maximum: number;
|
|
139
155
|
};
|
|
156
|
+
/**
|
|
157
|
+
* A table with no frame and no header, padded between its columns and never
|
|
158
|
+
* at its edges, so an expanded grid reaches both sides of its width. The
|
|
159
|
+
* reference's `grid` defaults, but for `padding`: Rich's is 0, which runs
|
|
160
|
+
* adjacent columns together, and this port's is one cell to the right.
|
|
161
|
+
*/
|
|
140
162
|
static grid(options?: Omit<TableOptions, "box" | "showHeader" | "showEdge">): Table;
|
|
141
163
|
private _frame;
|
|
142
164
|
/**
|
|
@@ -159,8 +181,23 @@ export declare class Table implements Renderable, Measurable {
|
|
|
159
181
|
* produce, and `expand` only in its `stretch`. They are resolved once, here, into uniform data, so
|
|
160
182
|
* `layoutTable` runs the same apportionment for every table and no sizing
|
|
161
183
|
* mode gets its own path through the width division.
|
|
184
|
+
*
|
|
185
|
+
* Cells are measured against the width left once the frame is paid, as the
|
|
186
|
+
* reference's `_measure_column` measures them. Padding and the floor are laid
|
|
187
|
+
* over whichever sizing the column has: they are the same for all three.
|
|
162
188
|
*/
|
|
163
189
|
private _columnDemands;
|
|
190
|
+
private _columnSizing;
|
|
191
|
+
/**
|
|
192
|
+
* The padding either side of column `index`'s content, and above and below
|
|
193
|
+
* one row of cells: the reference's `get_padding`. `collapsePadding` lets a
|
|
194
|
+
* cell's left padding and its row's bottom padding merge into the padding
|
|
195
|
+
* beside and below them; `padEdge: false` drops every side that meets the
|
|
196
|
+
* table's edge. Each side is the configured padding unless one of those two
|
|
197
|
+
* reduces it.
|
|
198
|
+
*/
|
|
199
|
+
private _columnPadding;
|
|
200
|
+
private _rowPadding;
|
|
164
201
|
/**
|
|
165
202
|
* Every cell column `index` draws, in draw order.
|
|
166
203
|
*
|
|
@@ -174,12 +211,13 @@ export declare class Table implements Renderable, Measurable {
|
|
|
174
211
|
*/
|
|
175
212
|
private _columnCells;
|
|
176
213
|
/**
|
|
177
|
-
* The widest cell in a column,
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
214
|
+
* The widest any cell in a column draws, and the narrowest the column can be
|
|
215
|
+
* without cutting one — the reference's `_measure_column` — or `undefined`
|
|
216
|
+
* when the column has no cell to measure. Zero is a column whose cells draw
|
|
217
|
+
* nothing — a gutter asks for its padding and nothing else — and is not the
|
|
218
|
+
* same answer. [LAW:types-are-the-program]
|
|
181
219
|
*/
|
|
182
|
-
private
|
|
220
|
+
private _cellRange;
|
|
183
221
|
/**
|
|
184
222
|
* A natural width held to the column's own `minWidth`/`maxWidth`.
|
|
185
223
|
*
|