@promptctl/rich-js 0.18.0 → 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.
Files changed (244) hide show
  1. package/README.md +9 -7
  2. package/dist/core/anchor.d.ts +45 -0
  3. package/dist/core/anchor.js +39 -0
  4. package/dist/core/ansi.d.ts +65 -0
  5. package/dist/core/ansi.js +231 -0
  6. package/dist/core/box.d.ts +145 -0
  7. package/dist/core/box.js +372 -0
  8. package/dist/core/cells.d.ts +192 -0
  9. package/dist/core/cells.js +334 -0
  10. package/dist/core/clock.d.ts +48 -0
  11. package/dist/core/clock.js +42 -0
  12. package/dist/core/color.d.ts +326 -0
  13. package/dist/core/color.js +1225 -0
  14. package/dist/core/console.d.ts +196 -0
  15. package/dist/core/console.js +596 -0
  16. package/dist/core/easing.d.ts +86 -0
  17. package/dist/core/easing.js +171 -0
  18. package/dist/core/emoji.d.ts +24 -0
  19. package/dist/core/emoji.js +391 -0
  20. package/dist/core/env.d.ts +16 -0
  21. package/dist/core/env.js +16 -0
  22. package/dist/core/export-html.d.ts +59 -0
  23. package/dist/core/export-html.js +197 -0
  24. package/dist/core/export-lines.d.ts +130 -0
  25. package/dist/core/export-lines.js +159 -0
  26. package/dist/core/export-svg.d.ts +49 -0
  27. package/dist/core/export-svg.js +213 -0
  28. package/dist/core/fnv1a.d.ts +10 -0
  29. package/dist/core/fnv1a.js +17 -0
  30. package/dist/core/highlighter.d.ts +33 -0
  31. package/dist/core/highlighter.js +190 -0
  32. package/dist/core/json.d.ts +27 -0
  33. package/dist/core/json.js +53 -0
  34. package/dist/core/markup.d.ts +140 -0
  35. package/dist/core/markup.js +654 -0
  36. package/dist/core/measure.d.ts +27 -0
  37. package/dist/core/measure.js +67 -0
  38. package/dist/core/memo.d.ts +19 -0
  39. package/dist/core/memo.js +34 -0
  40. package/dist/core/oklch.d.ts +161 -0
  41. package/dist/core/oklch.js +312 -0
  42. package/dist/core/osc8.d.ts +68 -0
  43. package/dist/core/osc8.js +78 -0
  44. package/dist/core/paint.d.ts +107 -0
  45. package/dist/core/paint.js +150 -0
  46. package/dist/core/place.d.ts +30 -0
  47. package/dist/core/place.js +49 -0
  48. package/dist/core/pretty.d.ts +247 -0
  49. package/dist/core/pretty.js +906 -0
  50. package/dist/core/protocol.d.ts +305 -0
  51. package/dist/core/protocol.js +183 -0
  52. package/dist/core/render.d.ts +87 -0
  53. package/dist/core/render.js +105 -0
  54. package/dist/core/segment.d.ts +162 -0
  55. package/dist/core/segment.js +488 -0
  56. package/dist/core/spinnerData.d.ts +12 -0
  57. package/dist/core/spinnerData.js +117 -0
  58. package/dist/core/strip.d.ts +152 -0
  59. package/dist/core/strip.js +326 -0
  60. package/dist/core/style.d.ts +189 -0
  61. package/dist/core/style.js +758 -0
  62. package/dist/core/subscription.d.ts +12 -0
  63. package/dist/core/subscription.js +12 -0
  64. package/dist/core/text.d.ts +283 -0
  65. package/dist/core/text.js +1097 -0
  66. package/dist/core/wrap.d.ts +46 -0
  67. package/dist/core/wrap.js +140 -0
  68. package/dist/host/app.d.ts +133 -0
  69. package/dist/host/app.js +285 -0
  70. package/dist/host/host-environment.d.ts +26 -0
  71. package/dist/host/host-environment.js +44 -0
  72. package/dist/host/index.d.ts +6 -0
  73. package/dist/host/index.js +3 -0
  74. package/dist/host/terminal-host.d.ts +180 -0
  75. package/dist/host/terminal-host.js +186 -0
  76. package/dist/index.d.ts +98 -0
  77. package/dist/index.js +114 -0
  78. package/dist/node/prompt.d.ts +34 -0
  79. package/dist/node/prompt.js +51 -0
  80. package/dist/node/save.d.ts +18 -0
  81. package/dist/node/save.js +24 -0
  82. package/dist/node/terminal-host.d.ts +114 -0
  83. package/dist/node/terminal-host.js +227 -0
  84. package/dist/node/traceback.d.ts +38 -0
  85. package/dist/node/traceback.js +98 -0
  86. package/dist/renderables/align.d.ts +16 -0
  87. package/dist/renderables/align.js +26 -0
  88. package/dist/renderables/columns.d.ts +77 -0
  89. package/dist/renderables/columns.js +191 -0
  90. package/dist/renderables/constrain.d.ts +15 -0
  91. package/dist/renderables/constrain.js +31 -0
  92. package/dist/renderables/effect.d.ts +98 -0
  93. package/dist/renderables/effect.js +160 -0
  94. package/dist/renderables/embed.d.ts +107 -0
  95. package/dist/renderables/embed.js +160 -0
  96. package/dist/renderables/flexStrip.d.ts +41 -0
  97. package/dist/renderables/flexStrip.js +200 -0
  98. package/dist/renderables/group.d.ts +14 -0
  99. package/dist/renderables/group.js +22 -0
  100. package/dist/renderables/layout.d.ts +75 -0
  101. package/dist/renderables/layout.js +223 -0
  102. package/dist/renderables/live.d.ts +74 -0
  103. package/dist/renderables/live.js +188 -0
  104. package/dist/renderables/markdown.d.ts +38 -0
  105. package/dist/renderables/markdown.js +587 -0
  106. package/dist/renderables/padding.d.ts +59 -0
  107. package/dist/renderables/padding.js +147 -0
  108. package/dist/renderables/panel.d.ts +114 -0
  109. package/dist/renderables/panel.js +303 -0
  110. package/dist/renderables/progress.d.ts +178 -0
  111. package/dist/renderables/progress.js +362 -0
  112. package/dist/renderables/progressBar.d.ts +31 -0
  113. package/dist/renderables/progressBar.js +64 -0
  114. package/dist/renderables/prompt.d.ts +71 -0
  115. package/dist/renderables/prompt.js +165 -0
  116. package/dist/renderables/ratio.d.ts +123 -0
  117. package/dist/renderables/ratio.js +213 -0
  118. package/dist/renderables/rule.d.ts +26 -0
  119. package/dist/renderables/rule.js +86 -0
  120. package/dist/renderables/spinner.d.ts +57 -0
  121. package/dist/renderables/spinner.js +103 -0
  122. package/dist/renderables/status.d.ts +29 -0
  123. package/dist/renderables/status.js +46 -0
  124. package/dist/renderables/syntax.d.ts +65 -0
  125. package/dist/renderables/syntax.js +166 -0
  126. package/dist/renderables/table.d.ts +232 -0
  127. package/dist/renderables/table.js +973 -0
  128. package/dist/renderables/traceback.d.ts +32 -0
  129. package/dist/renderables/traceback.js +279 -0
  130. package/dist/renderables/tree.d.ts +76 -0
  131. package/dist/renderables/tree.js +177 -0
  132. package/dist/renderables/viewport.d.ts +114 -0
  133. package/dist/renderables/viewport.js +196 -0
  134. package/dist/template-bindings/color-funcs.d.ts +109 -0
  135. package/dist/template-bindings/color-funcs.js +243 -0
  136. package/dist/template-bindings/helpers.d.ts +26 -0
  137. package/dist/template-bindings/helpers.js +33 -0
  138. package/dist/template-bindings/index.d.ts +119 -0
  139. package/dist/template-bindings/index.js +162 -0
  140. package/dist/template-bindings/palette-funcs.d.ts +96 -0
  141. package/dist/template-bindings/palette-funcs.js +145 -0
  142. package/dist/template-bindings/style-funcs.d.ts +28 -0
  143. package/dist/template-bindings/style-funcs.js +157 -0
  144. package/dist/themes/buildPalette.d.ts +57 -0
  145. package/dist/themes/buildPalette.js +100 -0
  146. package/dist/themes/colorMath.d.ts +94 -0
  147. package/dist/themes/colorMath.js +280 -0
  148. package/dist/themes/colorRef.d.ts +36 -0
  149. package/dist/themes/colorRef.js +78 -0
  150. package/dist/themes/data/ansi-tables.d.ts +14 -0
  151. package/dist/themes/data/ansi-tables.js +49 -0
  152. package/dist/themes/data/atom-one-dark.d.ts +3 -0
  153. package/dist/themes/data/atom-one-dark.js +177 -0
  154. package/dist/themes/data/atom-one-light.d.ts +3 -0
  155. package/dist/themes/data/atom-one-light.js +177 -0
  156. package/dist/themes/data/catppuccin-frappe.d.ts +3 -0
  157. package/dist/themes/data/catppuccin-frappe.js +177 -0
  158. package/dist/themes/data/catppuccin-latte.d.ts +3 -0
  159. package/dist/themes/data/catppuccin-latte.js +177 -0
  160. package/dist/themes/data/catppuccin-macchiato.d.ts +3 -0
  161. package/dist/themes/data/catppuccin-macchiato.js +177 -0
  162. package/dist/themes/data/catppuccin-mocha.d.ts +3 -0
  163. package/dist/themes/data/catppuccin-mocha.js +177 -0
  164. package/dist/themes/data/cyberpunk.d.ts +17 -0
  165. package/dist/themes/data/cyberpunk.js +193 -0
  166. package/dist/themes/data/default.d.ts +3 -0
  167. package/dist/themes/data/default.js +160 -0
  168. package/dist/themes/data/dracula.d.ts +3 -0
  169. package/dist/themes/data/dracula.js +177 -0
  170. package/dist/themes/data/flexoki.d.ts +3 -0
  171. package/dist/themes/data/flexoki.js +177 -0
  172. package/dist/themes/data/gruvbox.d.ts +3 -0
  173. package/dist/themes/data/gruvbox.js +177 -0
  174. package/dist/themes/data/index.d.ts +35 -0
  175. package/dist/themes/data/index.js +64 -0
  176. package/dist/themes/data/monokai.d.ts +3 -0
  177. package/dist/themes/data/monokai.js +177 -0
  178. package/dist/themes/data/nord.d.ts +3 -0
  179. package/dist/themes/data/nord.js +177 -0
  180. package/dist/themes/data/rose-pine-dawn.d.ts +3 -0
  181. package/dist/themes/data/rose-pine-dawn.js +177 -0
  182. package/dist/themes/data/rose-pine-moon.d.ts +3 -0
  183. package/dist/themes/data/rose-pine-moon.js +177 -0
  184. package/dist/themes/data/rose-pine.d.ts +3 -0
  185. package/dist/themes/data/rose-pine.js +177 -0
  186. package/dist/themes/data/solarized-dark.d.ts +3 -0
  187. package/dist/themes/data/solarized-dark.js +177 -0
  188. package/dist/themes/data/solarized-light.d.ts +3 -0
  189. package/dist/themes/data/solarized-light.js +177 -0
  190. package/dist/themes/data/svg-export.d.ts +3 -0
  191. package/dist/themes/data/svg-export.js +177 -0
  192. package/dist/themes/data/textual-ansi.d.ts +3 -0
  193. package/dist/themes/data/textual-ansi.js +160 -0
  194. package/dist/themes/data/textual-dark.d.ts +3 -0
  195. package/dist/themes/data/textual-dark.js +160 -0
  196. package/dist/themes/data/textual-light.d.ts +3 -0
  197. package/dist/themes/data/textual-light.js +160 -0
  198. package/dist/themes/data/tokyo-night.d.ts +3 -0
  199. package/dist/themes/data/tokyo-night.js +177 -0
  200. package/dist/themes/data/types.d.ts +31 -0
  201. package/dist/themes/data/types.js +10 -0
  202. package/dist/themes/palette.d.ts +45 -0
  203. package/dist/themes/palette.js +71 -0
  204. package/dist/themes/ramp.d.ts +70 -0
  205. package/dist/themes/ramp.js +103 -0
  206. package/dist/themes/registry.d.ts +44 -0
  207. package/dist/themes/registry.js +105 -0
  208. package/dist/themes/terminalThemes.d.ts +49 -0
  209. package/dist/themes/terminalThemes.js +63 -0
  210. package/dist/themes/transpose.d.ts +87 -0
  211. package/dist/themes/transpose.js +138 -0
  212. package/dist/widgets/button.d.ts +45 -0
  213. package/dist/widgets/button.js +177 -0
  214. package/dist/widgets/checkbox.d.ts +38 -0
  215. package/dist/widgets/checkbox.js +135 -0
  216. package/dist/widgets/dropdown.d.ts +64 -0
  217. package/dist/widgets/dropdown.js +416 -0
  218. package/dist/widgets/event-router.d.ts +71 -0
  219. package/dist/widgets/event-router.js +629 -0
  220. package/dist/widgets/focus-manager.d.ts +45 -0
  221. package/dist/widgets/focus-manager.js +191 -0
  222. package/dist/widgets/hit.d.ts +64 -0
  223. package/dist/widgets/hit.js +113 -0
  224. package/dist/widgets/index.d.ts +20 -0
  225. package/dist/widgets/index.js +14 -0
  226. package/dist/widgets/ink.d.ts +22 -0
  227. package/dist/widgets/ink.js +31 -0
  228. package/dist/widgets/slider.d.ts +54 -0
  229. package/dist/widgets/slider.js +247 -0
  230. package/dist/widgets/static-item.d.ts +34 -0
  231. package/dist/widgets/static-item.js +54 -0
  232. package/dist/widgets/text-input.d.ts +283 -0
  233. package/dist/widgets/text-input.js +1174 -0
  234. package/dist/widgets/themed-widget.d.ts +20 -0
  235. package/dist/widgets/themed-widget.js +89 -0
  236. package/dist/widgets/toggle.d.ts +41 -0
  237. package/dist/widgets/toggle.js +157 -0
  238. package/dist/widgets/types.d.ts +87 -0
  239. package/dist/widgets/types.js +30 -0
  240. package/dist/widgets/widget-app.d.ts +65 -0
  241. package/dist/widgets/widget-app.js +206 -0
  242. package/dist/widgets/widget-base.d.ts +42 -0
  243. package/dist/widgets/widget-base.js +172 -0
  244. package/package.json +16 -2
@@ -0,0 +1,105 @@
1
+ /**
2
+ * `renderToString` — stateless one-shot emission of a `Renderable` to a string
3
+ * of ANSI-encoded text. Pure function: same inputs produce byte-identical
4
+ * output. Does not write to `process.stdout` and does not require a `Console`
5
+ * instance.
6
+ *
7
+ * Note on `colorSystem: "auto"`: the `"auto"` spec resolves via
8
+ * `detectColorSystem`, which reads `process.env` and `process.stdout?.isTTY`
9
+ * by default. Callers that want a fully deterministic render must either pass
10
+ * an explicit `ColorDepth` enum / non-`"auto"` spec, or supply `env` and
11
+ * `isTTY` in the options so detection does not consult ambient process state.
12
+ *
13
+ * [LAW:single-enforcer] The Segment-to-ANSI conversion lives in `segmentToString`
14
+ * and is the single way a segment becomes wire bytes. `segmentsToString` is
15
+ * that encoding joined, and `Console._writeSegments`, `Painter` (every `Live`
16
+ * and `App` frame) and `renderToString` all go through it, so terminal output,
17
+ * live and app frames and string export agree by construction.
18
+ *
19
+ * [LAW:one-source-of-truth] What the encoding needs from where it writes
20
+ * arrives as one `Destination` value. Each caller resolves its destination
21
+ * once — spec, detection, and its own overrides — and hands it through whole,
22
+ * so a depth is never paired with a link setting taken from somewhere else.
23
+ *
24
+ * Every segment is written alone, exactly as Python Rich 9d8f9a3 writes it
25
+ * (`Console._render_buffer` calls `Style.render` per segment): its SGR codes
26
+ * open, its text, a reset, and an OSC 8 pair around all three when it carries
27
+ * a link. Two adjacent segments with equal codes are two runs, not one. That
28
+ * costs a reset and a reopen the terminal draws identically, and it is what
29
+ * lets a fixture generated from the reference hold any sequence of segments,
30
+ * rather than only those in which no two neighbours happen to share a style
31
+ * (rich-render-g5g8). The price of that is that where a renderable cuts its
32
+ * segments is now in the bytes, so a renderable pinned against the reference
33
+ * has to cut where the reference cuts, as `Box`'s rules and `Table`'s blank
34
+ * cell lines do. A link split across segments still hovers as one link,
35
+ * because every pair it becomes carries the id `osc8Open` derives from the URL.
36
+ *
37
+ * Colour and hyperlinks are two facts about the destination:
38
+ * `colorSystem === null` empties every segment's SGR codes, and
39
+ * `hyperlinks === false` drops every segment's link. A colour depth never
40
+ * removes a link — a hyperlink is not a colour, and a NO_COLOR terminal still
41
+ * follows OSC 8. This is where the port departs from the reference, whose
42
+ * `Style.render` returns bare text for a null colour system.
43
+ */
44
+ import { ColorDepth, resolveDestination } from "./color.js";
45
+ import { OSC8_CLOSE, osc8Open } from "./osc8.js";
46
+ const DEFAULT_WIDTH = 80;
47
+ /**
48
+ * Encodes one segment as ANSI bytes for `destination`: the reference's
49
+ * `Style.render` for that segment, and nothing for a control segment.
50
+ */
51
+ export function segmentToString(segment, destination) {
52
+ if (segment.isControl)
53
+ return "";
54
+ const { text, style } = segment;
55
+ // As the reference's `if not text` and `if style:` — no pair around nothing.
56
+ if (text.length === 0 || style === undefined)
57
+ return text;
58
+ // [LAW:one-type-per-behavior] Colour depth governs SGR only; hyperlinks are
59
+ // their own fact. Coupling them let a colour setting delete every control.
60
+ const codes = destination.colorSystem === null ? "" : style.toSgrCodes(destination.colorSystem);
61
+ const styled = codes.length > 0 ? `\x1b[${codes}m${text}\x1b[0m` : text;
62
+ const link = destination.hyperlinks ? style.link : undefined;
63
+ return link === undefined ? styled : `${osc8Open(link)}${styled}${OSC8_CLOSE}`;
64
+ }
65
+ /** Encodes a sequence of segments as ANSI bytes for `destination`, one segment at a time. */
66
+ export function segmentsToString(segments, destination) {
67
+ const parts = [];
68
+ for (const segment of segments)
69
+ parts.push(segmentToString(segment, destination));
70
+ return parts.join("");
71
+ }
72
+ export function renderToString(renderable, options) {
73
+ const width = options?.width ?? DEFAULT_WIDTH;
74
+ // [LAW:dataflow-not-control-flow] An absent spec is truecolor; an explicit
75
+ // `null` stays null (`??` would collapse it).
76
+ // [LAW:single-enforcer] Specs resolve through `resolveDestination`.
77
+ const detectOptions = {};
78
+ if (options?.env !== undefined)
79
+ detectOptions.env = options.env;
80
+ if (options?.isTTY !== undefined)
81
+ detectOptions.isTTY = options.isTTY;
82
+ const rawSpec = options?.colorSystem;
83
+ const resolved = resolveDestination(rawSpec === undefined ? ColorDepth.TRUECOLOR : rawSpec, detectOptions);
84
+ // [LAW:single-enforcer] This call's overrides are applied here, once, to
85
+ // make the one destination everything below is drawn for. `noColor` is a
86
+ // colour choice, so it overrides the depth and leaves hyperlinks to the
87
+ // destination; an explicit `hyperlinks` overrides what the destination takes.
88
+ const destination = {
89
+ colorSystem: options?.noColor ? null : resolved.colorSystem,
90
+ hyperlinks: options?.hyperlinks ?? resolved.hyperlinks,
91
+ };
92
+ const renderOptions = {
93
+ maxWidth: width,
94
+ isTerminal: false,
95
+ asciiOnly: options?.asciiOnly ?? false,
96
+ theme: options?.theme,
97
+ onStyleError: options?.onStyleError,
98
+ highlight: options?.highlight,
99
+ highlighter: options?.highlighter,
100
+ // [LAW:one-source-of-truth] The depth the segments below are encoded at,
101
+ // so a renderable measures what this very call will draw.
102
+ colorSystem: destination.colorSystem,
103
+ };
104
+ return segmentsToString(renderable.render(renderOptions), destination);
105
+ }
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Segment — the atomic rendering unit. Every piece of styled terminal output
3
+ * is represented as a Segment: (text, style?, control?).
4
+ */
5
+ import { type CellCol } from "./cells.js";
6
+ import { Style } from "./style.js";
7
+ import { type Anchor } from "./anchor.js";
8
+ export declare enum ControlType {
9
+ BELL = "bell",
10
+ CARRIAGE_RETURN = "carriage_return",
11
+ HOME = "home",
12
+ CLEAR = "clear",
13
+ SHOW_CURSOR = "show_cursor",
14
+ HIDE_CURSOR = "hide_cursor",
15
+ ENABLE_ALT_SCREEN = "enable_alt_screen",
16
+ DISABLE_ALT_SCREEN = "disable_alt_screen",
17
+ CURSOR_UP = "cursor_up",
18
+ CURSOR_DOWN = "cursor_down",
19
+ CURSOR_FORWARD = "cursor_forward",
20
+ CURSOR_BACKWARD = "cursor_backward",
21
+ CURSOR_MOVE_TO_COLUMN = "cursor_move_to_column",
22
+ CURSOR_MOVE_TO = "cursor_move_to",
23
+ ERASE_IN_LINE = "erase_in_line",
24
+ SET_WINDOW_TITLE = "set_window_title"
25
+ }
26
+ export type ControlCode = [ControlType, ...unknown[]];
27
+ export declare class Segment {
28
+ readonly text: string;
29
+ readonly style: Style | undefined;
30
+ readonly control: ControlCode[] | undefined;
31
+ constructor(text: string, style?: Style, control?: ControlCode[]);
32
+ get cellLength(): number;
33
+ get hasText(): boolean;
34
+ get isControl(): boolean;
35
+ /**
36
+ * Splits at a cell position. Returns [left, right]: the first `position`
37
+ * cells and the rest, so the two halves are exactly as wide as this one —
38
+ * `cutCells` blanks a wide glyph the cut goes through rather than keep it
39
+ * whole on a side it would widen by a cell.
40
+ *
41
+ * [LAW:single-enforcer] The right half starts `position` cells further into
42
+ * whatever drew it, and its anchor says so; see `./anchor.ts`.
43
+ */
44
+ splitCells(position: CellCol): [Segment, Segment];
45
+ private static _line;
46
+ static line(): Segment;
47
+ /**
48
+ * `lines`, as drawn by `owner`: every segment stamped with the row and
49
+ * column of its first cell, wrapping whatever anchor it already carried.
50
+ * Control segments occupy no cell and are left as they are. `firstRow` is
51
+ * the owner's row that `lines[0]` is, for output that arrives in pieces.
52
+ */
53
+ static anchorLines(lines: Segment[][], owner: object, firstRow?: number): Segment[][];
54
+ /**
55
+ * The anchor of the cell at column `x` of row `y` in a composed frame, or
56
+ * `undefined` when that cell was drawn by no owner or lies outside the frame.
57
+ */
58
+ static anchorAt(lines: readonly (readonly Segment[])[], x: number, y: number): Anchor | undefined;
59
+ /**
60
+ * Yields segments with combined styles.
61
+ */
62
+ static applyStyle(segments: Iterable<Segment>, style?: Style, postStyle?: Style): Iterable<Segment>;
63
+ /**
64
+ * Filters segments by control status.
65
+ */
66
+ static filterControl(segments: Iterable<Segment>, isControl: boolean): Iterable<Segment>;
67
+ /**
68
+ * Splits segments at newlines. Yields arrays of segments per line.
69
+ */
70
+ static splitLines(segments: Iterable<Segment>): Segment[][];
71
+ /**
72
+ * Adjusts a line of segments to exactly `width` cells.
73
+ */
74
+ static adjustLineLength(line: Segment[], width: number, style?: Style, pad?: boolean): Segment[];
75
+ /**
76
+ * Crops a renderable's output so no line exceeds `width`, leaving short lines
77
+ * alone and the line structure exactly as it arrived.
78
+ *
79
+ * [LAW:single-enforcer] `adjustLineLength` is where a width is enforced, but
80
+ * it takes one line and a container holding arbitrary content has a stream of
81
+ * them. Without this step the container has to trust content to honour the
82
+ * offer, and content that ignores it overflows the region — which is how a
83
+ * `Layout` leaf and a `Tree` label came to emit forty cells into a one-cell
84
+ * offer while `Panel` and `Padding`, which split and adjust, did not.
85
+ *
86
+ * One segment in, one segment out, shortening text and nothing else — so the
87
+ * line structure that arrives is the line structure that leaves. Two earlier
88
+ * shapes of this both decided how many lines there were and both were wrong:
89
+ * built on `splitLines`, which cannot tell `"abc"` from `"abc\n"`, it invented
90
+ * a trailing newline and dropped the row of an empty `Tree` label entirely,
91
+ * running its guides into the next row; rebuilt to accumulate lines, it
92
+ * dropped the zero-width-but-present line `RichText` emits at an offer of 0,
93
+ * and a row split rendered nothing at all. A crop shortens; it does not count.
94
+ *
95
+ * A wide glyph the edge cuts through leaves a space in the cell it would have
96
+ * half-filled, so a cropped line still reaches the edge — the reference's
97
+ * `set_cell_size`, which `splitText` already is. An unbounded `width` crops
98
+ * nothing, and a segment the crop did not change leaves as itself.
99
+ */
100
+ static cropLines(segments: Iterable<Segment>, width: number): Iterable<Segment>;
101
+ /**
102
+ * Splits a renderable's output into rows, each exactly `width` cells:
103
+ * short rows padded with spaces, long ones cut.
104
+ */
105
+ static splitAndCropLines(segments: Iterable<Segment>, width: number): Segment[][];
106
+ /**
107
+ * Returns total cell width of a line. Ignores control segments.
108
+ */
109
+ static getLineLength(line: Segment[]): number;
110
+ /**
111
+ * Returns [width, height] of a set of lines.
112
+ */
113
+ static getShape(lines: Segment[][]): [number, number];
114
+ /**
115
+ * Composes cells side by side into full lines. Each cell contributes its
116
+ * own lines cropped/padded to its declared width; a cell shorter than the
117
+ * tallest is filled with blank space so the grid stays aligned. Adjacent
118
+ * cells are separated by a gutter of spaces, and each merged row ends with a
119
+ * line break. This is the single side-by-side merge used by every horizontal
120
+ * layout (Columns grid rows, Layout row splits).
121
+ */
122
+ static mergeHorizontal(cells: readonly {
123
+ readonly lines: Segment[][];
124
+ readonly width: number;
125
+ }[], gutter?: number): Iterable<Segment>;
126
+ /**
127
+ * Merges contiguous segments with the same style.
128
+ */
129
+ static simplify(segments: Iterable<Segment>): Iterable<Segment>;
130
+ /**
131
+ * Yields segments with links removed.
132
+ */
133
+ static stripLinks(segments: Iterable<Segment>): Iterable<Segment>;
134
+ /**
135
+ * Yields segments with all styles removed.
136
+ */
137
+ static stripStyles(segments: Iterable<Segment>): Iterable<Segment>;
138
+ /**
139
+ * Yields segments with colors removed but attributes preserved.
140
+ */
141
+ static removeColor(segments: Iterable<Segment>): Iterable<Segment>;
142
+ /**
143
+ * Divides segments at cell positions. Yields arrays of segments for each section.
144
+ */
145
+ static divide(segments: Segment[], cuts: number[]): Segment[][];
146
+ /**
147
+ * Pads below to fill height.
148
+ */
149
+ static alignTop(lines: Segment[][], width: number, height: number, style: Style): Segment[][];
150
+ /**
151
+ * Pads above to fill height. Content at bottom.
152
+ */
153
+ static alignBottom(lines: Segment[][], width: number, height: number, style: Style): Segment[][];
154
+ /**
155
+ * Pads above and below. Content in middle.
156
+ */
157
+ static alignMiddle(lines: Segment[][], width: number, height: number, style: Style): Segment[][];
158
+ /**
159
+ * Forces lines to exactly width x height.
160
+ */
161
+ static setShape(lines: Segment[][], width: number, height: number, style?: Style): Segment[][];
162
+ }