@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.
- package/README.md +9 -7
- package/dist/core/anchor.d.ts +45 -0
- package/dist/core/anchor.js +39 -0
- package/dist/core/ansi.d.ts +65 -0
- package/dist/core/ansi.js +231 -0
- package/dist/core/box.d.ts +145 -0
- package/dist/core/box.js +372 -0
- package/dist/core/cells.d.ts +192 -0
- package/dist/core/cells.js +334 -0
- package/dist/core/clock.d.ts +48 -0
- package/dist/core/clock.js +42 -0
- package/dist/core/color.d.ts +326 -0
- package/dist/core/color.js +1225 -0
- package/dist/core/console.d.ts +196 -0
- package/dist/core/console.js +596 -0
- package/dist/core/easing.d.ts +86 -0
- package/dist/core/easing.js +171 -0
- package/dist/core/emoji.d.ts +24 -0
- package/dist/core/emoji.js +391 -0
- package/dist/core/env.d.ts +16 -0
- package/dist/core/env.js +16 -0
- package/dist/core/export-html.d.ts +59 -0
- package/dist/core/export-html.js +197 -0
- package/dist/core/export-lines.d.ts +130 -0
- package/dist/core/export-lines.js +159 -0
- 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 +33 -0
- package/dist/core/highlighter.js +190 -0
- package/dist/core/json.d.ts +27 -0
- package/dist/core/json.js +53 -0
- package/dist/core/markup.d.ts +140 -0
- package/dist/core/markup.js +654 -0
- package/dist/core/measure.d.ts +27 -0
- package/dist/core/measure.js +67 -0
- package/dist/core/memo.d.ts +19 -0
- package/dist/core/memo.js +34 -0
- package/dist/core/oklch.d.ts +161 -0
- package/dist/core/oklch.js +312 -0
- package/dist/core/osc8.d.ts +68 -0
- package/dist/core/osc8.js +78 -0
- package/dist/core/paint.d.ts +107 -0
- package/dist/core/paint.js +150 -0
- package/dist/core/place.d.ts +30 -0
- package/dist/core/place.js +49 -0
- package/dist/core/pretty.d.ts +247 -0
- package/dist/core/pretty.js +906 -0
- package/dist/core/protocol.d.ts +305 -0
- package/dist/core/protocol.js +183 -0
- package/dist/core/render.d.ts +87 -0
- package/dist/core/render.js +105 -0
- package/dist/core/segment.d.ts +162 -0
- package/dist/core/segment.js +488 -0
- package/dist/core/spinnerData.d.ts +12 -0
- package/dist/core/spinnerData.js +117 -0
- package/dist/core/strip.d.ts +152 -0
- package/dist/core/strip.js +326 -0
- package/dist/core/style.d.ts +189 -0
- package/dist/core/style.js +758 -0
- package/dist/core/subscription.d.ts +12 -0
- package/dist/core/subscription.js +12 -0
- package/dist/core/text.d.ts +283 -0
- package/dist/core/text.js +1097 -0
- package/dist/core/wrap.d.ts +46 -0
- package/dist/core/wrap.js +140 -0
- package/dist/host/app.d.ts +133 -0
- package/dist/host/app.js +285 -0
- package/dist/host/host-environment.d.ts +26 -0
- package/dist/host/host-environment.js +44 -0
- package/dist/host/index.d.ts +6 -0
- package/dist/host/index.js +3 -0
- package/dist/host/terminal-host.d.ts +180 -0
- package/dist/host/terminal-host.js +186 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +114 -0
- package/dist/node/prompt.d.ts +34 -0
- package/dist/node/prompt.js +51 -0
- package/dist/node/save.d.ts +18 -0
- package/dist/node/save.js +24 -0
- package/dist/node/terminal-host.d.ts +114 -0
- package/dist/node/terminal-host.js +227 -0
- package/dist/node/traceback.d.ts +38 -0
- package/dist/node/traceback.js +98 -0
- package/dist/renderables/align.d.ts +16 -0
- package/dist/renderables/align.js +26 -0
- package/dist/renderables/columns.d.ts +77 -0
- package/dist/renderables/columns.js +191 -0
- package/dist/renderables/constrain.d.ts +15 -0
- package/dist/renderables/constrain.js +31 -0
- package/dist/renderables/effect.d.ts +98 -0
- package/dist/renderables/effect.js +160 -0
- package/dist/renderables/embed.d.ts +107 -0
- package/dist/renderables/embed.js +160 -0
- package/dist/renderables/flexStrip.d.ts +41 -0
- package/dist/renderables/flexStrip.js +200 -0
- package/dist/renderables/group.d.ts +14 -0
- package/dist/renderables/group.js +22 -0
- package/dist/renderables/layout.d.ts +75 -0
- package/dist/renderables/layout.js +223 -0
- package/dist/renderables/live.d.ts +74 -0
- package/dist/renderables/live.js +188 -0
- package/dist/renderables/markdown.d.ts +38 -0
- package/dist/renderables/markdown.js +587 -0
- package/dist/renderables/padding.d.ts +59 -0
- package/dist/renderables/padding.js +147 -0
- package/dist/renderables/panel.d.ts +114 -0
- package/dist/renderables/panel.js +303 -0
- package/dist/renderables/progress.d.ts +178 -0
- package/dist/renderables/progress.js +362 -0
- package/dist/renderables/progressBar.d.ts +31 -0
- package/dist/renderables/progressBar.js +64 -0
- package/dist/renderables/prompt.d.ts +71 -0
- package/dist/renderables/prompt.js +165 -0
- package/dist/renderables/ratio.d.ts +123 -0
- package/dist/renderables/ratio.js +213 -0
- package/dist/renderables/rule.d.ts +26 -0
- package/dist/renderables/rule.js +86 -0
- package/dist/renderables/spinner.d.ts +57 -0
- package/dist/renderables/spinner.js +103 -0
- package/dist/renderables/status.d.ts +29 -0
- package/dist/renderables/status.js +46 -0
- package/dist/renderables/syntax.d.ts +65 -0
- package/dist/renderables/syntax.js +166 -0
- package/dist/renderables/table.d.ts +232 -0
- package/dist/renderables/table.js +973 -0
- package/dist/renderables/traceback.d.ts +32 -0
- package/dist/renderables/traceback.js +279 -0
- package/dist/renderables/tree.d.ts +76 -0
- package/dist/renderables/tree.js +177 -0
- package/dist/renderables/viewport.d.ts +114 -0
- package/dist/renderables/viewport.js +196 -0
- package/dist/template-bindings/color-funcs.d.ts +109 -0
- package/dist/template-bindings/color-funcs.js +243 -0
- package/dist/template-bindings/helpers.d.ts +26 -0
- package/dist/template-bindings/helpers.js +33 -0
- package/dist/template-bindings/index.d.ts +119 -0
- package/dist/template-bindings/index.js +162 -0
- package/dist/template-bindings/palette-funcs.d.ts +96 -0
- package/dist/template-bindings/palette-funcs.js +145 -0
- package/dist/template-bindings/style-funcs.d.ts +28 -0
- package/dist/template-bindings/style-funcs.js +157 -0
- package/dist/themes/buildPalette.d.ts +57 -0
- package/dist/themes/buildPalette.js +100 -0
- package/dist/themes/colorMath.d.ts +94 -0
- package/dist/themes/colorMath.js +280 -0
- package/dist/themes/colorRef.d.ts +36 -0
- package/dist/themes/colorRef.js +78 -0
- package/dist/themes/data/ansi-tables.d.ts +14 -0
- package/dist/themes/data/ansi-tables.js +49 -0
- package/dist/themes/data/atom-one-dark.d.ts +3 -0
- package/dist/themes/data/atom-one-dark.js +177 -0
- package/dist/themes/data/atom-one-light.d.ts +3 -0
- package/dist/themes/data/atom-one-light.js +177 -0
- package/dist/themes/data/catppuccin-frappe.d.ts +3 -0
- package/dist/themes/data/catppuccin-frappe.js +177 -0
- package/dist/themes/data/catppuccin-latte.d.ts +3 -0
- package/dist/themes/data/catppuccin-latte.js +177 -0
- package/dist/themes/data/catppuccin-macchiato.d.ts +3 -0
- package/dist/themes/data/catppuccin-macchiato.js +177 -0
- package/dist/themes/data/catppuccin-mocha.d.ts +3 -0
- package/dist/themes/data/catppuccin-mocha.js +177 -0
- package/dist/themes/data/cyberpunk.d.ts +17 -0
- package/dist/themes/data/cyberpunk.js +193 -0
- package/dist/themes/data/default.d.ts +3 -0
- package/dist/themes/data/default.js +160 -0
- package/dist/themes/data/dracula.d.ts +3 -0
- package/dist/themes/data/dracula.js +177 -0
- package/dist/themes/data/flexoki.d.ts +3 -0
- package/dist/themes/data/flexoki.js +177 -0
- package/dist/themes/data/gruvbox.d.ts +3 -0
- package/dist/themes/data/gruvbox.js +177 -0
- package/dist/themes/data/index.d.ts +35 -0
- package/dist/themes/data/index.js +64 -0
- package/dist/themes/data/monokai.d.ts +3 -0
- package/dist/themes/data/monokai.js +177 -0
- package/dist/themes/data/nord.d.ts +3 -0
- package/dist/themes/data/nord.js +177 -0
- package/dist/themes/data/rose-pine-dawn.d.ts +3 -0
- package/dist/themes/data/rose-pine-dawn.js +177 -0
- package/dist/themes/data/rose-pine-moon.d.ts +3 -0
- package/dist/themes/data/rose-pine-moon.js +177 -0
- package/dist/themes/data/rose-pine.d.ts +3 -0
- package/dist/themes/data/rose-pine.js +177 -0
- package/dist/themes/data/solarized-dark.d.ts +3 -0
- package/dist/themes/data/solarized-dark.js +177 -0
- package/dist/themes/data/solarized-light.d.ts +3 -0
- package/dist/themes/data/solarized-light.js +177 -0
- package/dist/themes/data/svg-export.d.ts +3 -0
- package/dist/themes/data/svg-export.js +177 -0
- package/dist/themes/data/textual-ansi.d.ts +3 -0
- package/dist/themes/data/textual-ansi.js +160 -0
- package/dist/themes/data/textual-dark.d.ts +3 -0
- package/dist/themes/data/textual-dark.js +160 -0
- package/dist/themes/data/textual-light.d.ts +3 -0
- package/dist/themes/data/textual-light.js +160 -0
- package/dist/themes/data/tokyo-night.d.ts +3 -0
- package/dist/themes/data/tokyo-night.js +177 -0
- package/dist/themes/data/types.d.ts +31 -0
- package/dist/themes/data/types.js +10 -0
- package/dist/themes/palette.d.ts +45 -0
- package/dist/themes/palette.js +71 -0
- package/dist/themes/ramp.d.ts +70 -0
- package/dist/themes/ramp.js +103 -0
- package/dist/themes/registry.d.ts +44 -0
- package/dist/themes/registry.js +105 -0
- package/dist/themes/terminalThemes.d.ts +49 -0
- package/dist/themes/terminalThemes.js +63 -0
- package/dist/themes/transpose.d.ts +87 -0
- package/dist/themes/transpose.js +138 -0
- package/dist/widgets/button.d.ts +45 -0
- package/dist/widgets/button.js +177 -0
- package/dist/widgets/checkbox.d.ts +38 -0
- package/dist/widgets/checkbox.js +135 -0
- package/dist/widgets/dropdown.d.ts +64 -0
- package/dist/widgets/dropdown.js +416 -0
- package/dist/widgets/event-router.d.ts +71 -0
- package/dist/widgets/event-router.js +629 -0
- package/dist/widgets/focus-manager.d.ts +45 -0
- package/dist/widgets/focus-manager.js +191 -0
- package/dist/widgets/hit.d.ts +64 -0
- package/dist/widgets/hit.js +113 -0
- package/dist/widgets/index.d.ts +20 -0
- package/dist/widgets/index.js +14 -0
- package/dist/widgets/ink.d.ts +22 -0
- package/dist/widgets/ink.js +31 -0
- package/dist/widgets/slider.d.ts +54 -0
- package/dist/widgets/slider.js +247 -0
- package/dist/widgets/static-item.d.ts +34 -0
- package/dist/widgets/static-item.js +54 -0
- package/dist/widgets/text-input.d.ts +283 -0
- package/dist/widgets/text-input.js +1174 -0
- package/dist/widgets/themed-widget.d.ts +20 -0
- package/dist/widgets/themed-widget.js +89 -0
- package/dist/widgets/toggle.d.ts +41 -0
- package/dist/widgets/toggle.js +157 -0
- package/dist/widgets/types.d.ts +87 -0
- package/dist/widgets/types.js +30 -0
- package/dist/widgets/widget-app.d.ts +65 -0
- package/dist/widgets/widget-app.js +206 -0
- package/dist/widgets/widget-base.d.ts +42 -0
- package/dist/widgets/widget-base.js +172 -0
- package/package.json +16 -2
package/README.md
CHANGED
|
@@ -342,7 +342,7 @@ console.print(new Greeting());
|
|
|
342
342
|
|
|
343
343
|
```typescript
|
|
344
344
|
const console = new Console({
|
|
345
|
-
colorSystem: "truecolor", // null | "auto" | "
|
|
345
|
+
colorSystem: "truecolor", // null | "auto" | "none" | "ansi" | "256" | "truecolor"
|
|
346
346
|
width: 120, // override terminal width
|
|
347
347
|
stderr: true, // write to stderr
|
|
348
348
|
record: true, // record output for export
|
|
@@ -354,14 +354,15 @@ const console = new Console({
|
|
|
354
354
|
When `record: true`, export output after the fact:
|
|
355
355
|
|
|
356
356
|
```typescript
|
|
357
|
-
import {
|
|
357
|
+
import { SOLARIZED_LIGHT, SVG_EXPORT_THEME } from "@promptctl/rich-js";
|
|
358
|
+
import { saveSvg } from "@promptctl/rich-js/node/save";
|
|
358
359
|
|
|
359
|
-
const text = console.exportText();
|
|
360
|
-
const html = console.exportHtml();
|
|
361
|
-
|
|
360
|
+
const text = console.exportText({ clear: false });
|
|
361
|
+
const html = console.exportHtml({ theme: SOLARIZED_LIGHT, clear: false });
|
|
362
|
+
saveSvg(console, "output.svg", { theme: SVG_EXPORT_THEME });
|
|
362
363
|
```
|
|
363
364
|
|
|
364
|
-
`saveText`
|
|
365
|
+
`saveText`, `saveHtml` and `saveSvg` live on the `node/save` subpath because they import `node:fs`; the main barrel stays browser-safe. The [console guide](https://brandon-fryslie.github.io/rich-js/master/console#exporting) covers what each export draws, the themes it takes, and when it clears the recording.
|
|
365
366
|
|
|
366
367
|
## Demos
|
|
367
368
|
|
|
@@ -384,8 +385,9 @@ npm run demo
|
|
|
384
385
|
| `npm run demo-inputs` | rich-config | The widgets — checkbox, toggle, slider, dropdown, text input, button — driving a theme and palette viewer. |
|
|
385
386
|
| `npm run demo:dropdown` | dropdown-demo | Three `Dropdown` widgets: a plain one, one filtered as you type, and one whose options change every few seconds. |
|
|
386
387
|
| `npm run template-bindings` | rich-template-bindings | Type a template on the left and watch it render on the right. |
|
|
387
|
-
| `npm run themes-and-color-studio` | themes-and-color-studio | A printed tour of colours, palettes, bundled themes, and contrast. Prints once and exits; set `EXPORT_HTML=out.html` to save it
|
|
388
|
+
| `npm run themes-and-color-studio` | themes-and-color-studio | A printed tour of colours, palettes, bundled themes, and contrast. Prints once and exits; set any of `EXPORT_HTML=out.html`, `EXPORT_SVG=out.svg` and `EXPORT_TEXT=out.txt` to also save it to each file named. |
|
|
388
389
|
| `npm run strip` | rich-strip | Every built-in `Joiner`, printed side by side. Prints once and exits. |
|
|
390
|
+
| `npm run effects-feel` | effects-feel | Shimmer, pulse, drift, sparkle, fade-in and dissolve-out on a powerline strip and a run of text, at a frame rate, colour depth and ground you choose. A demo for agreeing how the effects feel; `npm run effects-feel -- --help` lists the flags. |
|
|
389
391
|
| `npm run markup-plugins` | rich-markup-plugins | Custom markup tags registered through `MarkupRegistry`. Prints once and exits. |
|
|
390
392
|
| `npm run viewport` | rich-viewport | A cursor walking a list taller than its window, kept in view by `Viewport.ensureVisible`. |
|
|
391
393
|
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anchor — where a cell sat in the output of the thing that drew it.
|
|
3
|
+
*
|
|
4
|
+
* A widget nested inside a `Layout` cell inside a `Panel` does not know where
|
|
5
|
+
* it lands on screen, and nothing can tell it before it renders: `Align`
|
|
6
|
+
* centres each line only after rendering it, so the lines of one widget can
|
|
7
|
+
* start at different columns, and a `Viewport` shows whichever of its
|
|
8
|
+
* content's rows its offset selects. An origin handed down through the render
|
|
9
|
+
* options would be a number each container has to compute before it knows
|
|
10
|
+
* the answer, and one more thing every container must forward correctly.
|
|
11
|
+
*
|
|
12
|
+
* So the position travels up instead, on the cells themselves. The owner
|
|
13
|
+
* stamps each segment of its output with its row and column there
|
|
14
|
+
* (`Segment.anchorLines`), the stamp rides on the segment's `Style`, which
|
|
15
|
+
* every container already carries through untouched, and whoever holds the
|
|
16
|
+
* composed frame reads any cell's owner and position straight off it
|
|
17
|
+
* (`Segment.anchorAt`). Containers do nothing, so no container can get it
|
|
18
|
+
* wrong.
|
|
19
|
+
*
|
|
20
|
+
* [LAW:single-enforcer] Two things can falsify a stamp. Cutting a segment in
|
|
21
|
+
* two starts the right half at a later column than the stamp names:
|
|
22
|
+
* `Segment.splitCells` is where a segment is cut, and it shifts the right
|
|
23
|
+
* half's anchor (`shiftAnchor`); a crop that keeps the left half keeps a stamp
|
|
24
|
+
* that is already true. Laying the text out again moves every cell: a
|
|
25
|
+
* `RichText` does that, so it admits no anchor (`admitStyle` in `./text.ts`),
|
|
26
|
+
* and the owner that renders it stamps what it draws.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* The position of a segment's first cell in its owner's output, and the
|
|
30
|
+
* anchor that segment carried before this owner stamped it — the owner nested
|
|
31
|
+
* inside this one, if any. Innermost last: follow `inner` to reach the owner
|
|
32
|
+
* that drew the cell itself.
|
|
33
|
+
*/
|
|
34
|
+
export interface Anchor {
|
|
35
|
+
/** The thing that drew this cell, compared by identity. */
|
|
36
|
+
readonly owner: object;
|
|
37
|
+
readonly row: number;
|
|
38
|
+
readonly col: number;
|
|
39
|
+
readonly inner: Anchor | undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The anchor of the cell `cells` to the right of the one `anchor` names, at
|
|
43
|
+
* every level of the nesting — each level names the same cell.
|
|
44
|
+
*/
|
|
45
|
+
export declare function shiftAnchor(anchor: Anchor, cells: number): Anchor;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anchor — where a cell sat in the output of the thing that drew it.
|
|
3
|
+
*
|
|
4
|
+
* A widget nested inside a `Layout` cell inside a `Panel` does not know where
|
|
5
|
+
* it lands on screen, and nothing can tell it before it renders: `Align`
|
|
6
|
+
* centres each line only after rendering it, so the lines of one widget can
|
|
7
|
+
* start at different columns, and a `Viewport` shows whichever of its
|
|
8
|
+
* content's rows its offset selects. An origin handed down through the render
|
|
9
|
+
* options would be a number each container has to compute before it knows
|
|
10
|
+
* the answer, and one more thing every container must forward correctly.
|
|
11
|
+
*
|
|
12
|
+
* So the position travels up instead, on the cells themselves. The owner
|
|
13
|
+
* stamps each segment of its output with its row and column there
|
|
14
|
+
* (`Segment.anchorLines`), the stamp rides on the segment's `Style`, which
|
|
15
|
+
* every container already carries through untouched, and whoever holds the
|
|
16
|
+
* composed frame reads any cell's owner and position straight off it
|
|
17
|
+
* (`Segment.anchorAt`). Containers do nothing, so no container can get it
|
|
18
|
+
* wrong.
|
|
19
|
+
*
|
|
20
|
+
* [LAW:single-enforcer] Two things can falsify a stamp. Cutting a segment in
|
|
21
|
+
* two starts the right half at a later column than the stamp names:
|
|
22
|
+
* `Segment.splitCells` is where a segment is cut, and it shifts the right
|
|
23
|
+
* half's anchor (`shiftAnchor`); a crop that keeps the left half keeps a stamp
|
|
24
|
+
* that is already true. Laying the text out again moves every cell: a
|
|
25
|
+
* `RichText` does that, so it admits no anchor (`admitStyle` in `./text.ts`),
|
|
26
|
+
* and the owner that renders it stamps what it draws.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* The anchor of the cell `cells` to the right of the one `anchor` names, at
|
|
30
|
+
* every level of the nesting — each level names the same cell.
|
|
31
|
+
*/
|
|
32
|
+
export function shiftAnchor(anchor, cells) {
|
|
33
|
+
return {
|
|
34
|
+
owner: anchor.owner,
|
|
35
|
+
row: anchor.row,
|
|
36
|
+
col: anchor.col + cells,
|
|
37
|
+
inner: anchor.inner && shiftAnchor(anchor.inner, cells),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI bytes back into styled text — a port of Rich's `AnsiDecoder`
|
|
3
|
+
* (rich/ansi.py) and `Text.from_ansi`.
|
|
4
|
+
*
|
|
5
|
+
* The rendering pipeline runs one way, `Style` → SGR bytes; this runs it
|
|
6
|
+
* backwards, for output some program already wrote: a capture of an example's
|
|
7
|
+
* own `new Console()`, a CLI's output shown inside a Panel, a log replayed into
|
|
8
|
+
* a Table cell.
|
|
9
|
+
*
|
|
10
|
+
* [LAW:types-are-the-program] Every colour decodes to the `ColorSpec` its
|
|
11
|
+
* escape names — `31` the standard colour 1, `38;5;n` palette index n,
|
|
12
|
+
* `38;2;r;g;b` that truecolor — and none is resolved to RGB here. A standard
|
|
13
|
+
* colour is a slot in whatever theme draws it, so one captured run exports
|
|
14
|
+
* correctly under a light theme and a dark one; resolved here, dark mode would
|
|
15
|
+
* show light mode's colours. Resolution belongs to `export-lines`.
|
|
16
|
+
*
|
|
17
|
+
* [LAW:types-are-the-program] The link is decoder state of its own, beside
|
|
18
|
+
* the SGR style, not a field of it: a terminal ends a hyperlink only at an OSC
|
|
19
|
+
* 8 close, and an SGR reset inside the link leaves it open. Rich keeps the
|
|
20
|
+
* link in the SGR style, so its reset drops it.
|
|
21
|
+
*
|
|
22
|
+
* Carriage returns are the other departure, and the same argument. Rich splits
|
|
23
|
+
* lines with Python's `splitlines`, which also breaks at `\r`, so its `a\rb`
|
|
24
|
+
* is two lines. Here a line ends only at `\n`, and `\r` returns to the first
|
|
25
|
+
* column, so later text overwrites earlier text character by character:
|
|
26
|
+
* `50%\r100%` is `100%`, `Downloading\rDone` is `Doneloading`, and `done\r`
|
|
27
|
+
* is still `done`. Columns are counted in characters, not cells, so a wide
|
|
28
|
+
* character overwritten by a narrow one is where this and a terminal differ.
|
|
29
|
+
* Erase in line (`\x1b[K`) is honoured for the same reason, because a redraw
|
|
30
|
+
* is usually `\r\x1b[K` and the old text must not show through a shorter new
|
|
31
|
+
* one.
|
|
32
|
+
*
|
|
33
|
+
* Everything else follows Rich: malformed SGR parameters are skipped rather
|
|
34
|
+
* than refused, and every other escape is dropped. It is not a terminal
|
|
35
|
+
* emulator — any other cursor movement is dropped, not performed.
|
|
36
|
+
*
|
|
37
|
+
* Tier 5 of `src/core/`: it builds `RichText`, so it sits above `text`, and
|
|
38
|
+
* `RichText` cannot offer a `fromAnsi` static without importing upward.
|
|
39
|
+
*/
|
|
40
|
+
import { RichText } from "./text.js";
|
|
41
|
+
import type { RichTextOptions } from "./text.js";
|
|
42
|
+
/**
|
|
43
|
+
* A stateful decoder: the style an escape sets carries on across lines, and
|
|
44
|
+
* across calls, as it does on a terminal. Use one decoder per stream and hand
|
|
45
|
+
* it whole lines, so output read a line at a time decodes as it would have
|
|
46
|
+
* all at once. It buffers nothing: a chunk cut mid-line or mid-escape decodes
|
|
47
|
+
* as the line it appears to be.
|
|
48
|
+
*/
|
|
49
|
+
export declare class AnsiDecoder {
|
|
50
|
+
private sgr;
|
|
51
|
+
private link;
|
|
52
|
+
/** One `RichText` per line of `ansi`; a final newline ends a line rather than starting one. */
|
|
53
|
+
decode(ansi: string): RichText[];
|
|
54
|
+
/**
|
|
55
|
+
* One line of output, holding no `\n`, written the way a terminal writes
|
|
56
|
+
* it: `\r` returns to the first column, and text overwrites from there.
|
|
57
|
+
*/
|
|
58
|
+
decodeLine(line: string): RichText;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* `ansi` as one `RichText`, its lines joined by `\n` — Rich's
|
|
62
|
+
* `Text.from_ansi`. `options` describe the result the way they describe any
|
|
63
|
+
* `RichText`.
|
|
64
|
+
*/
|
|
65
|
+
export declare function decodeAnsi(ansi: string, options?: RichTextOptions): RichText;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI bytes back into styled text — a port of Rich's `AnsiDecoder`
|
|
3
|
+
* (rich/ansi.py) and `Text.from_ansi`.
|
|
4
|
+
*
|
|
5
|
+
* The rendering pipeline runs one way, `Style` → SGR bytes; this runs it
|
|
6
|
+
* backwards, for output some program already wrote: a capture of an example's
|
|
7
|
+
* own `new Console()`, a CLI's output shown inside a Panel, a log replayed into
|
|
8
|
+
* a Table cell.
|
|
9
|
+
*
|
|
10
|
+
* [LAW:types-are-the-program] Every colour decodes to the `ColorSpec` its
|
|
11
|
+
* escape names — `31` the standard colour 1, `38;5;n` palette index n,
|
|
12
|
+
* `38;2;r;g;b` that truecolor — and none is resolved to RGB here. A standard
|
|
13
|
+
* colour is a slot in whatever theme draws it, so one captured run exports
|
|
14
|
+
* correctly under a light theme and a dark one; resolved here, dark mode would
|
|
15
|
+
* show light mode's colours. Resolution belongs to `export-lines`.
|
|
16
|
+
*
|
|
17
|
+
* [LAW:types-are-the-program] The link is decoder state of its own, beside
|
|
18
|
+
* the SGR style, not a field of it: a terminal ends a hyperlink only at an OSC
|
|
19
|
+
* 8 close, and an SGR reset inside the link leaves it open. Rich keeps the
|
|
20
|
+
* link in the SGR style, so its reset drops it.
|
|
21
|
+
*
|
|
22
|
+
* Carriage returns are the other departure, and the same argument. Rich splits
|
|
23
|
+
* lines with Python's `splitlines`, which also breaks at `\r`, so its `a\rb`
|
|
24
|
+
* is two lines. Here a line ends only at `\n`, and `\r` returns to the first
|
|
25
|
+
* column, so later text overwrites earlier text character by character:
|
|
26
|
+
* `50%\r100%` is `100%`, `Downloading\rDone` is `Doneloading`, and `done\r`
|
|
27
|
+
* is still `done`. Columns are counted in characters, not cells, so a wide
|
|
28
|
+
* character overwritten by a narrow one is where this and a terminal differ.
|
|
29
|
+
* Erase in line (`\x1b[K`) is honoured for the same reason, because a redraw
|
|
30
|
+
* is usually `\r\x1b[K` and the old text must not show through a shorter new
|
|
31
|
+
* one.
|
|
32
|
+
*
|
|
33
|
+
* Everything else follows Rich: malformed SGR parameters are skipped rather
|
|
34
|
+
* than refused, and every other escape is dropped. It is not a terminal
|
|
35
|
+
* emulator — any other cursor movement is dropped, not performed.
|
|
36
|
+
*
|
|
37
|
+
* Tier 5 of `src/core/`: it builds `RichText`, so it sits above `text`, and
|
|
38
|
+
* `RichText` cannot offer a `fromAnsi` static without importing upward.
|
|
39
|
+
*/
|
|
40
|
+
import { ColorSpec } from "./color.js";
|
|
41
|
+
import { osc8Sequences } from "./osc8.js";
|
|
42
|
+
import { ATTRIBUTE_NAMES, ATTRIBUTE_SGR, NULL_STYLE, Style } from "./style.js";
|
|
43
|
+
import { RichText } from "./text.js";
|
|
44
|
+
/**
|
|
45
|
+
* Every escape but OSC 8, which `osc8Sequences` reads before this runs. In
|
|
46
|
+
* order: a carriage return; an SGR sequence (group 1, its parameters — a
|
|
47
|
+
* private marker such as the `>` of `\x1b[>4;2m` makes it some other CSI);
|
|
48
|
+
* erase in line (group 2, its mode); any other CSI sequence; any other string
|
|
49
|
+
* escape — OSC, DCS, APC, PM, SOS — run to the terminators OSC 8 accepts or
|
|
50
|
+
* cut off by the end of the line; any other escape, ECMA-48's intermediates
|
|
51
|
+
* and one final byte (`\x1b(B`, `\x1b)0`, `\x1b#8`, `\x1bc`). Only the first
|
|
52
|
+
* three become tokens.
|
|
53
|
+
*/
|
|
54
|
+
const ESCAPE = /\r|\x1b\[([0-9;:]*)m|\x1b\[([012]?)K|\x1b\[[0-?]*[ -/]*[@-~]|\x1b[\]P_^X][\s\S]*?(?:\x07|\x1b\\|\x9c|$)|\x1b[ -/]*[0-~]/g;
|
|
55
|
+
function* escapeTokens(bytes) {
|
|
56
|
+
let at = 0;
|
|
57
|
+
for (const match of bytes.matchAll(ESCAPE)) {
|
|
58
|
+
if (match.index > at)
|
|
59
|
+
yield { kind: "text", text: bytes.slice(at, match.index) };
|
|
60
|
+
if (match[0] === "\r")
|
|
61
|
+
yield { kind: "return" };
|
|
62
|
+
if (match[1] !== undefined)
|
|
63
|
+
yield { kind: "sgr", params: match[1] };
|
|
64
|
+
if (match[2] !== undefined)
|
|
65
|
+
yield { kind: "erase", mode: (match[2] || "0") };
|
|
66
|
+
at = match.index + match[0].length;
|
|
67
|
+
}
|
|
68
|
+
if (at < bytes.length)
|
|
69
|
+
yield { kind: "text", text: bytes.slice(at) };
|
|
70
|
+
}
|
|
71
|
+
// [LAW:one-source-of-truth] OSC 8 is read by the reader `osc8.ts` owns, so
|
|
72
|
+
// the terminators a link may end with cannot differ between writing and
|
|
73
|
+
// reading it back.
|
|
74
|
+
function* tokens(line) {
|
|
75
|
+
let at = 0;
|
|
76
|
+
for (const sequence of osc8Sequences(line)) {
|
|
77
|
+
yield* escapeTokens(line.slice(at, sequence.index));
|
|
78
|
+
yield { kind: "link", uri: sequence.uri };
|
|
79
|
+
at = sequence.index + sequence.length;
|
|
80
|
+
}
|
|
81
|
+
yield* escapeTokens(line.slice(at));
|
|
82
|
+
}
|
|
83
|
+
function adding(options) {
|
|
84
|
+
const added = new Style(options);
|
|
85
|
+
return (style) => style.add(added);
|
|
86
|
+
}
|
|
87
|
+
function next(rest) {
|
|
88
|
+
const step = rest.next();
|
|
89
|
+
return step.done ? undefined : step.value;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* `5;n` or `2;r;g;b`, the arguments of `38` and `48`. A sequence cut short
|
|
93
|
+
* names no colour, and the codes it did consume are spent, as in Rich.
|
|
94
|
+
*/
|
|
95
|
+
function extendedColor(rest) {
|
|
96
|
+
const kind = next(rest);
|
|
97
|
+
if (kind === 5) {
|
|
98
|
+
const n = next(rest);
|
|
99
|
+
return n === undefined ? undefined : ColorSpec.fromAnsi(n);
|
|
100
|
+
}
|
|
101
|
+
if (kind === 2) {
|
|
102
|
+
const [r, g, b] = [next(rest), next(rest), next(rest)];
|
|
103
|
+
return b === undefined ? undefined : ColorSpec.fromRgb(r, g, b);
|
|
104
|
+
}
|
|
105
|
+
return undefined;
|
|
106
|
+
}
|
|
107
|
+
// [LAW:dataflow-not-control-flow] Every code is an operation on the style,
|
|
108
|
+
// reset included; a code this table does not name is the identity.
|
|
109
|
+
const SGR_OPS = new Map([
|
|
110
|
+
[0, () => NULL_STYLE],
|
|
111
|
+
// [LAW:one-source-of-truth] The codes that turn an attribute on are the
|
|
112
|
+
// ones `Style.toSgrCodes` writes; only the codes that turn one off are ours.
|
|
113
|
+
...ATTRIBUTE_NAMES.map((name) => [ATTRIBUTE_SGR[name], adding({ [name]: true })]),
|
|
114
|
+
[22, adding({ bold: false, dim: false })],
|
|
115
|
+
[23, adding({ italic: false })],
|
|
116
|
+
// ECMA-48: 24 is "neither singly nor doubly underlined", 25 "steady" at
|
|
117
|
+
// either speed. Rich's table clears only the first of each pair.
|
|
118
|
+
[24, adding({ underline: false, underline2: false })],
|
|
119
|
+
[25, adding({ blink: false, blink2: false })],
|
|
120
|
+
[27, adding({ reverse: false })],
|
|
121
|
+
[28, adding({ conceal: false })],
|
|
122
|
+
[29, adding({ strike: false })],
|
|
123
|
+
[38, (style, rest) => style.add(new Style({ color: extendedColor(rest) }))],
|
|
124
|
+
[39, adding({ color: ColorSpec.default() })],
|
|
125
|
+
[48, (style, rest) => style.add(new Style({ bgcolor: extendedColor(rest) }))],
|
|
126
|
+
[49, adding({ bgcolor: ColorSpec.default() })],
|
|
127
|
+
// Underline colour has no field on Style; its arguments are still spent, or
|
|
128
|
+
// `58;2;1;2;3` would read on as bold, dim and italic.
|
|
129
|
+
[58, (style, rest) => (extendedColor(rest), style)],
|
|
130
|
+
[54, adding({ frame: false, encircle: false })],
|
|
131
|
+
[55, adding({ overline: false })],
|
|
132
|
+
...Array.from({ length: 8 }, (_, n) => [
|
|
133
|
+
[30 + n, adding({ color: ColorSpec.fromAnsi(n) })],
|
|
134
|
+
[40 + n, adding({ bgcolor: ColorSpec.fromAnsi(n) })],
|
|
135
|
+
[90 + n, adding({ color: ColorSpec.fromAnsi(n + 8) })],
|
|
136
|
+
[100 + n, adding({ bgcolor: ColorSpec.fromAnsi(n + 8) })],
|
|
137
|
+
]).flat(),
|
|
138
|
+
]);
|
|
139
|
+
const identity = (style) => style;
|
|
140
|
+
/**
|
|
141
|
+
* `params` applied to `style`. An empty parameter is 0 and one above 255 is
|
|
142
|
+
* 255; one that is not a number — a colon sub-parameter — is skipped, as in
|
|
143
|
+
* Rich.
|
|
144
|
+
*/
|
|
145
|
+
function applySgr(style, params) {
|
|
146
|
+
const codes = params
|
|
147
|
+
.split(";")
|
|
148
|
+
.filter((code) => /^\d*$/.test(code))
|
|
149
|
+
.map((code) => Math.min(255, Number(code)))
|
|
150
|
+
.values();
|
|
151
|
+
let result = style;
|
|
152
|
+
for (const code of codes)
|
|
153
|
+
result = (SGR_OPS.get(code) ?? identity)(result, codes);
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
const BLANK = [" ", NULL_STYLE];
|
|
157
|
+
/** Erase in line: the cells before the cursor go blank, the ones from it on go. */
|
|
158
|
+
function erase(cells, column, mode) {
|
|
159
|
+
if (mode !== "0")
|
|
160
|
+
cells.fill(BLANK, 0, Math.min(column + 1, cells.length));
|
|
161
|
+
if (mode !== "1")
|
|
162
|
+
cells.length = Math.min(column, cells.length);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* A stateful decoder: the style an escape sets carries on across lines, and
|
|
166
|
+
* across calls, as it does on a terminal. Use one decoder per stream and hand
|
|
167
|
+
* it whole lines, so output read a line at a time decodes as it would have
|
|
168
|
+
* all at once. It buffers nothing: a chunk cut mid-line or mid-escape decodes
|
|
169
|
+
* as the line it appears to be.
|
|
170
|
+
*/
|
|
171
|
+
export class AnsiDecoder {
|
|
172
|
+
sgr = NULL_STYLE;
|
|
173
|
+
link = undefined;
|
|
174
|
+
/** One `RichText` per line of `ansi`; a final newline ends a line rather than starting one. */
|
|
175
|
+
decode(ansi) {
|
|
176
|
+
return (ansi.match(/[^\n]*\n|[^\n]+/g) ?? []).map((line) => this.decodeLine(line.replace(/\r?\n$/, "")));
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* One line of output, holding no `\n`, written the way a terminal writes
|
|
180
|
+
* it: `\r` returns to the first column, and text overwrites from there.
|
|
181
|
+
*/
|
|
182
|
+
decodeLine(line) {
|
|
183
|
+
const cells = [];
|
|
184
|
+
let column = 0;
|
|
185
|
+
for (const token of tokens(line)) {
|
|
186
|
+
switch (token.kind) {
|
|
187
|
+
case "text": {
|
|
188
|
+
const style = this.sgr.withLink(this.link);
|
|
189
|
+
for (const char of token.text)
|
|
190
|
+
cells[column++] = [char, style];
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
case "return":
|
|
194
|
+
column = 0;
|
|
195
|
+
break;
|
|
196
|
+
case "erase":
|
|
197
|
+
erase(cells, column, token.mode);
|
|
198
|
+
break;
|
|
199
|
+
case "sgr":
|
|
200
|
+
this.sgr = applySgr(this.sgr, token.params);
|
|
201
|
+
break;
|
|
202
|
+
case "link":
|
|
203
|
+
this.link = token.uri === "" ? undefined : token.uri;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const runs = [];
|
|
208
|
+
for (const [char, style] of cells) {
|
|
209
|
+
const last = runs.at(-1);
|
|
210
|
+
if (last?.[1].equals(style))
|
|
211
|
+
last[0] += char;
|
|
212
|
+
else
|
|
213
|
+
runs.push([char, style]);
|
|
214
|
+
}
|
|
215
|
+
return RichText.assemble(runs);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* `ansi` as one `RichText`, its lines joined by `\n` — Rich's
|
|
220
|
+
* `Text.from_ansi`. `options` describe the result the way they describe any
|
|
221
|
+
* `RichText`.
|
|
222
|
+
*/
|
|
223
|
+
export function decodeAnsi(ansi, options) {
|
|
224
|
+
const result = new RichText("", options);
|
|
225
|
+
new AnsiDecoder().decode(ansi).forEach((line, index) => {
|
|
226
|
+
if (index > 0)
|
|
227
|
+
result.append("\n");
|
|
228
|
+
result.append(line);
|
|
229
|
+
});
|
|
230
|
+
return result;
|
|
231
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Box-drawing character sets for borders and table grids.
|
|
3
|
+
*
|
|
4
|
+
* A style is declared as an 8x4 character grid — one line per row a table can
|
|
5
|
+
* draw, one column per position within that row:
|
|
6
|
+
*
|
|
7
|
+
* ┌─┬┐ top border
|
|
8
|
+
* │ ││ header content
|
|
9
|
+
* ├─┼┤ header separator
|
|
10
|
+
* │ ││ body content
|
|
11
|
+
* ├─┼┤ row separator
|
|
12
|
+
* ├─┼┤ footer separator
|
|
13
|
+
* │ ││ footer content
|
|
14
|
+
* └─┴┘ bottom border
|
|
15
|
+
*
|
|
16
|
+
* [LAW:one-source-of-truth] The grid is the shape the reference implementation
|
|
17
|
+
* (Python Rich's `box.py`) publishes these glyphs in, so a constant below can
|
|
18
|
+
* be diffed against it character for character. The eighteen named fields this
|
|
19
|
+
* replaced were a second, differently-shaped map of the same territory, and it
|
|
20
|
+
* had drifted: seven of the nineteen constants carried wrong glyphs, and the
|
|
21
|
+
* field named `mid` held the reference's line 3 while the reference's `mid_*`
|
|
22
|
+
* is line 4 — so reading the reference name-for-name swapped a separator for a
|
|
23
|
+
* content row. Named row fields are gone for that reason; a row is reached by
|
|
24
|
+
* what it is (`getRow`, `getContentChars`), never by a name that can be
|
|
25
|
+
* mismatched to a line.
|
|
26
|
+
*/
|
|
27
|
+
import { Segment } from "./segment.js";
|
|
28
|
+
import type { Style } from "./style.js";
|
|
29
|
+
/** A rule spanning the table: the top and bottom borders, and every separator. */
|
|
30
|
+
export interface EdgeChars {
|
|
31
|
+
left: string;
|
|
32
|
+
horizontal: string;
|
|
33
|
+
cross: string;
|
|
34
|
+
right: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The verticals framing a row of cells. A content line of the grid has no
|
|
38
|
+
* horizontal of its own — its fill column is a placeholder the cells occupy.
|
|
39
|
+
*/
|
|
40
|
+
export interface ContentChars {
|
|
41
|
+
left: string;
|
|
42
|
+
vertical: string;
|
|
43
|
+
right: string;
|
|
44
|
+
}
|
|
45
|
+
export type RowLevel = "head" | "row" | "foot" | "mid";
|
|
46
|
+
export interface SubstituteOptions {
|
|
47
|
+
asciiOnly?: boolean;
|
|
48
|
+
safe?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export declare class Box {
|
|
51
|
+
readonly top: EdgeChars;
|
|
52
|
+
readonly bottom: EdgeChars;
|
|
53
|
+
private readonly grid;
|
|
54
|
+
private readonly headContent;
|
|
55
|
+
private readonly headSeparator;
|
|
56
|
+
private readonly bodyContent;
|
|
57
|
+
private readonly rowSeparator;
|
|
58
|
+
private readonly footSeparator;
|
|
59
|
+
private readonly footContent;
|
|
60
|
+
/**
|
|
61
|
+
* [LAW:parse-dont-validate] The one crossing between a grid string and box
|
|
62
|
+
* glyphs. A `Box` cannot exist without eight rows of four characters, so no
|
|
63
|
+
* consumer below ever re-checks the shape of the data it reads.
|
|
64
|
+
*/
|
|
65
|
+
constructor(grid: string);
|
|
66
|
+
/**
|
|
67
|
+
* Renders the top border row for given column widths.
|
|
68
|
+
*/
|
|
69
|
+
getTop(widths: readonly number[], style?: Style, edge?: boolean): Segment[];
|
|
70
|
+
/**
|
|
71
|
+
* Renders the separator drawn *above* a row at `level` — the head separator
|
|
72
|
+
* under the header, the row separator between body rows, the foot separator
|
|
73
|
+
* above the footer.
|
|
74
|
+
*/
|
|
75
|
+
getRow(widths: readonly number[], level: RowLevel, style?: Style, edge?: boolean): Segment[];
|
|
76
|
+
/**
|
|
77
|
+
* The verticals that frame a content row at `level` — the counterpart to
|
|
78
|
+
* `getRow`, which draws the separator between two such rows.
|
|
79
|
+
*/
|
|
80
|
+
getContentChars(level: RowLevel): ContentChars;
|
|
81
|
+
/**
|
|
82
|
+
* Renders the bottom border row.
|
|
83
|
+
*/
|
|
84
|
+
getBottom(widths: readonly number[], style?: Style, edge?: boolean): Segment[];
|
|
85
|
+
/**
|
|
86
|
+
* The box to draw with when the platform cannot render this one as written.
|
|
87
|
+
*
|
|
88
|
+
* `asciiOnly` gives up a box that spends non-ASCII glyphs for `ASCII`, and
|
|
89
|
+
* leaves the four already-ASCII styles as they are — a caller that chose
|
|
90
|
+
* MARKDOWN or ASCII_DOUBLE_HEAD asked for that frame and it is already
|
|
91
|
+
* drawable, so answering with `ASCII` would trade a frame the terminal
|
|
92
|
+
* supports for a different one it equally supports. `safe` squares off the
|
|
93
|
+
* rounded corners a legacy Windows terminal draws as blanks.
|
|
94
|
+
*/
|
|
95
|
+
substitute(options?: SubstituteOptions): Box;
|
|
96
|
+
private safeSubstitute;
|
|
97
|
+
/**
|
|
98
|
+
* The nearest box that spends no special glyphs on a header — what a table
|
|
99
|
+
* with `showHeader: false` draws with. A box whose head row already matches
|
|
100
|
+
* its body is its own answer, so this is the identity for fourteen of the
|
|
101
|
+
* nineteen shipped styles.
|
|
102
|
+
*
|
|
103
|
+
* It stands beside `substitute` rather than joining it because the two ask
|
|
104
|
+
* unrelated questions: `substitute` asks what the *platform* can draw, this
|
|
105
|
+
* asks what the *table* contains. Nothing correlates them, so a caller that
|
|
106
|
+
* wants both wants both, and a shared options bag would only multiply the
|
|
107
|
+
* combinations either one has to reason about. [LAW:no-mode-explosion]
|
|
108
|
+
*
|
|
109
|
+
* [LAW:types-are-the-program] The relation is keyed on the grid, not on
|
|
110
|
+
* object identity as the reference's dict is. A `Box` is wholly determined by
|
|
111
|
+
* its grid — that is what the constructor takes and all eight rows derive
|
|
112
|
+
* from — so two boxes with one grid must answer this alike. Identity keying
|
|
113
|
+
* would say otherwise the moment a box arrived by any route but the shipped
|
|
114
|
+
* constant, and `safeSubstitute` above builds exactly such a box: a fresh
|
|
115
|
+
* instance carrying an unchanged grid.
|
|
116
|
+
*/
|
|
117
|
+
plainHeaded(): Box;
|
|
118
|
+
/**
|
|
119
|
+
* [LAW:dataflow-not-control-flow] Every full-width rule the box can draw is
|
|
120
|
+
* this one join; which rule it is arrives as four characters, not a branch.
|
|
121
|
+
* The rule is one segment, as the reference's `get_top` is one string, so
|
|
122
|
+
* its bytes are one styled run.
|
|
123
|
+
*/
|
|
124
|
+
private getEdge;
|
|
125
|
+
private getRowChars;
|
|
126
|
+
}
|
|
127
|
+
export declare const ASCII: Box;
|
|
128
|
+
export declare const ASCII2: Box;
|
|
129
|
+
export declare const ASCII_DOUBLE_HEAD: Box;
|
|
130
|
+
export declare const SQUARE: Box;
|
|
131
|
+
export declare const SQUARE_DOUBLE_HEAD: Box;
|
|
132
|
+
export declare const MINIMAL: Box;
|
|
133
|
+
export declare const MINIMAL_HEAVY_HEAD: Box;
|
|
134
|
+
export declare const MINIMAL_DOUBLE_HEAD: Box;
|
|
135
|
+
export declare const SIMPLE: Box;
|
|
136
|
+
export declare const SIMPLE_HEAD: Box;
|
|
137
|
+
export declare const SIMPLE_HEAVY: Box;
|
|
138
|
+
export declare const HORIZONTALS: Box;
|
|
139
|
+
export declare const ROUNDED: Box;
|
|
140
|
+
export declare const HEAVY: Box;
|
|
141
|
+
export declare const HEAVY_EDGE: Box;
|
|
142
|
+
export declare const HEAVY_HEAD: Box;
|
|
143
|
+
export declare const DOUBLE: Box;
|
|
144
|
+
export declare const DOUBLE_EDGE: Box;
|
|
145
|
+
export declare const MARKDOWN: Box;
|