@promptctl/rich-js 0.18.1 → 0.20.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 (169) hide show
  1. package/README.md +11 -8
  2. package/dist/core/box.d.ts +3 -1
  3. package/dist/core/box.js +6 -13
  4. package/dist/core/cells.d.ts +61 -28
  5. package/dist/core/cells.js +171 -124
  6. package/dist/core/clock.d.ts +48 -0
  7. package/dist/core/clock.js +42 -0
  8. package/dist/core/color.d.ts +99 -18
  9. package/dist/core/color.js +334 -146
  10. package/dist/core/console.d.ts +38 -7
  11. package/dist/core/console.js +159 -90
  12. package/dist/core/easing.d.ts +86 -0
  13. package/dist/core/easing.js +171 -0
  14. package/dist/core/env.d.ts +16 -0
  15. package/dist/core/env.js +16 -0
  16. package/dist/core/export-html.js +1 -4
  17. package/dist/core/export-lines.d.ts +22 -13
  18. package/dist/core/export-lines.js +37 -19
  19. package/dist/core/export-svg.d.ts +49 -0
  20. package/dist/core/export-svg.js +213 -0
  21. package/dist/core/fnv1a.d.ts +10 -0
  22. package/dist/core/fnv1a.js +17 -0
  23. package/dist/core/highlighter.d.ts +2 -2
  24. package/dist/core/highlighter.js +113 -47
  25. package/dist/core/json.js +1 -1
  26. package/dist/core/markup.d.ts +28 -7
  27. package/dist/core/markup.js +235 -312
  28. package/dist/core/measure.d.ts +3 -3
  29. package/dist/core/measure.js +12 -7
  30. package/dist/core/memo.d.ts +19 -0
  31. package/dist/core/memo.js +34 -0
  32. package/dist/core/noise.d.ts +31 -0
  33. package/dist/core/noise.js +94 -0
  34. package/dist/core/osc8.d.ts +6 -6
  35. package/dist/core/osc8.js +9 -21
  36. package/dist/core/paint.d.ts +107 -0
  37. package/dist/core/paint.js +161 -0
  38. package/dist/core/place.d.ts +1 -1
  39. package/dist/core/place.js +4 -6
  40. package/dist/core/pretty.d.ts +126 -2
  41. package/dist/core/pretty.js +571 -105
  42. package/dist/core/protocol.d.ts +43 -3
  43. package/dist/core/protocol.js +23 -2
  44. package/dist/core/render.d.ts +33 -30
  45. package/dist/core/render.js +43 -83
  46. package/dist/core/segment.d.ts +6 -5
  47. package/dist/core/segment.js +11 -15
  48. package/dist/core/selection.d.ts +12 -0
  49. package/dist/core/selection.js +14 -0
  50. package/dist/core/strip.d.ts +116 -74
  51. package/dist/core/strip.js +266 -217
  52. package/dist/core/style.d.ts +27 -7
  53. package/dist/core/style.js +106 -41
  54. package/dist/core/text.d.ts +43 -16
  55. package/dist/core/text.js +180 -59
  56. package/dist/core/wrap.d.ts +5 -0
  57. package/dist/core/wrap.js +16 -3
  58. package/dist/host/app.d.ts +95 -17
  59. package/dist/host/app.js +201 -61
  60. package/dist/host/index.d.ts +4 -1
  61. package/dist/host/index.js +1 -0
  62. package/dist/host/input.d.ts +84 -0
  63. package/dist/host/input.js +498 -0
  64. package/dist/host/terminal-host.d.ts +15 -2
  65. package/dist/host/terminal-host.js +2 -0
  66. package/dist/index.d.ts +26 -14
  67. package/dist/index.js +17 -7
  68. package/dist/node/prompt.d.ts +13 -0
  69. package/dist/node/prompt.js +30 -9
  70. package/dist/node/save.d.ts +4 -3
  71. package/dist/node/save.js +6 -3
  72. package/dist/node/terminal-host.d.ts +10 -2
  73. package/dist/node/terminal-host.js +7 -0
  74. package/dist/node/traceback.d.ts +2 -1
  75. package/dist/node/traceback.js +3 -39
  76. package/dist/renderables/align.js +2 -9
  77. package/dist/renderables/columns.d.ts +45 -29
  78. package/dist/renderables/columns.js +142 -103
  79. package/dist/renderables/constrain.js +6 -12
  80. package/dist/renderables/effect.d.ts +113 -0
  81. package/dist/renderables/effect.js +182 -0
  82. package/dist/renderables/effects.d.ts +252 -0
  83. package/dist/renderables/effects.js +565 -0
  84. package/dist/renderables/embed.d.ts +94 -31
  85. package/dist/renderables/embed.js +141 -45
  86. package/dist/renderables/group.d.ts +6 -3
  87. package/dist/renderables/group.js +5 -0
  88. package/dist/renderables/layout.d.ts +6 -23
  89. package/dist/renderables/layout.js +24 -113
  90. package/dist/renderables/list-view.d.ts +42 -0
  91. package/dist/renderables/list-view.js +78 -0
  92. package/dist/renderables/live.d.ts +40 -16
  93. package/dist/renderables/live.js +96 -83
  94. package/dist/renderables/markdown.d.ts +16 -2
  95. package/dist/renderables/markdown.js +521 -118
  96. package/dist/renderables/padding.d.ts +22 -1
  97. package/dist/renderables/padding.js +30 -24
  98. package/dist/renderables/panel.d.ts +31 -33
  99. package/dist/renderables/panel.js +137 -141
  100. package/dist/renderables/progress.d.ts +110 -16
  101. package/dist/renderables/progress.js +212 -81
  102. package/dist/renderables/progressBar.d.ts +24 -4
  103. package/dist/renderables/progressBar.js +78 -23
  104. package/dist/renderables/prompt.d.ts +37 -15
  105. package/dist/renderables/prompt.js +125 -85
  106. package/dist/renderables/ratio.d.ts +123 -0
  107. package/dist/renderables/ratio.js +213 -0
  108. package/dist/renderables/rule.d.ts +3 -2
  109. package/dist/renderables/rule.js +50 -52
  110. package/dist/renderables/spinner.d.ts +28 -2
  111. package/dist/renderables/spinner.js +52 -19
  112. package/dist/renderables/status.d.ts +13 -7
  113. package/dist/renderables/status.js +15 -29
  114. package/dist/renderables/syntax.d.ts +37 -7
  115. package/dist/renderables/syntax.js +134 -83
  116. package/dist/renderables/table.d.ts +58 -20
  117. package/dist/renderables/table.js +373 -197
  118. package/dist/renderables/traceback.d.ts +5 -4
  119. package/dist/renderables/traceback.js +239 -68
  120. package/dist/renderables/tree.d.ts +10 -2
  121. package/dist/renderables/tree.js +61 -34
  122. package/dist/renderables/viewport.d.ts +30 -0
  123. package/dist/renderables/viewport.js +61 -7
  124. package/dist/template-bindings/color-funcs.d.ts +31 -9
  125. package/dist/template-bindings/color-funcs.js +40 -14
  126. package/dist/template-bindings/helpers.d.ts +4 -2
  127. package/dist/template-bindings/helpers.js +5 -20
  128. package/dist/template-bindings/index.d.ts +29 -17
  129. package/dist/template-bindings/index.js +36 -20
  130. package/dist/template-bindings/palette-funcs.d.ts +3 -1
  131. package/dist/template-bindings/palette-funcs.js +11 -7
  132. package/dist/template-bindings/style-funcs.js +4 -2
  133. package/dist/themes/buildPalette.d.ts +24 -3
  134. package/dist/themes/buildPalette.js +52 -8
  135. package/dist/themes/colorMath.d.ts +29 -17
  136. package/dist/themes/colorMath.js +74 -48
  137. package/dist/themes/colorRef.d.ts +2 -17
  138. package/dist/themes/colorRef.js +13 -31
  139. package/dist/themes/palette.d.ts +24 -0
  140. package/dist/themes/palette.js +46 -3
  141. package/dist/themes/ramp.d.ts +21 -34
  142. package/dist/themes/ramp.js +23 -42
  143. package/dist/themes/registry.js +39 -28
  144. package/dist/widgets/button.d.ts +2 -6
  145. package/dist/widgets/button.js +9 -40
  146. package/dist/widgets/checkbox.d.ts +2 -5
  147. package/dist/widgets/checkbox.js +9 -31
  148. package/dist/widgets/dropdown.d.ts +2 -5
  149. package/dist/widgets/dropdown.js +17 -51
  150. package/dist/widgets/event-router.d.ts +31 -40
  151. package/dist/widgets/event-router.js +52 -483
  152. package/dist/widgets/index.d.ts +2 -1
  153. package/dist/widgets/ink.d.ts +22 -0
  154. package/dist/widgets/ink.js +31 -0
  155. package/dist/widgets/slider.d.ts +2 -5
  156. package/dist/widgets/slider.js +11 -34
  157. package/dist/widgets/text-input.d.ts +19 -10
  158. package/dist/widgets/text-input.js +156 -147
  159. package/dist/widgets/themed-widget.d.ts +20 -0
  160. package/dist/widgets/themed-widget.js +89 -0
  161. package/dist/widgets/toggle.d.ts +2 -5
  162. package/dist/widgets/toggle.js +8 -31
  163. package/dist/widgets/types.d.ts +8 -25
  164. package/dist/widgets/types.js +8 -0
  165. package/dist/widgets/widget-app.d.ts +24 -7
  166. package/dist/widgets/widget-app.js +35 -18
  167. package/dist/widgets/widget-base.d.ts +2 -0
  168. package/dist/widgets/widget-base.js +9 -2
  169. package/package.json +31 -17
@@ -3,6 +3,7 @@
3
3
  */
4
4
  import { COLOR_NAMES, ColorSpec, SURFACE_BLACK, } from "./color.js";
5
5
  import { shiftAnchor } from "./anchor.js";
6
+ import { Memo } from "./memo.js";
6
7
  // [LAW:one-way-deps] `core/style` depends only on `core/color`. The substrate
7
8
  // a translucent colour is flattened over is `SURFACE_BLACK`, defined beside
8
9
  // `compositeOver`.
@@ -66,8 +67,8 @@ export class StyleSyntaxError extends Error {
66
67
  this.name = "StyleSyntaxError";
67
68
  }
68
69
  }
69
- // [LAW:one-source-of-truth] Parse cache is the single source for parsed Style instances
70
- const styleParseCache = new Map();
70
+ // [LAW:one-source-of-truth] The single source for parsed Style instances.
71
+ const styleParseMemo = new Memo();
71
72
  // --- Style ---
72
73
  export class Style {
73
74
  color;
@@ -95,7 +96,7 @@ export class Style {
95
96
  anchor;
96
97
  constructor(options = {}) {
97
98
  this.color = resolveColor(options.color);
98
- this.bgcolor = resolveColor(options.bgcolor);
99
+ this.bgcolor = resolveBackground(options.bgcolor);
99
100
  this.bold = options.bold;
100
101
  this.dim = options.dim;
101
102
  this.italic = options.italic;
@@ -251,8 +252,7 @@ export class Style {
251
252
  /**
252
253
  * Returns the SGR parameter list this style emits (e.g. `"1;31;48;2;0;0;255"`),
253
254
  * or `""` when the style has no SGR contribution. Excludes OSC 8 link bytes —
254
- * links are not SGR. The segment encoder (`segmentsToString`) uses this
255
- * string as the group key for adjacent-same-style coalescing and wraps it in
255
+ * links are not SGR. The segment encoder (`segmentToString`) wraps it in
256
256
  * `\x1b[...m`; styled text reaches the wire only through that encoder.
257
257
  *
258
258
  * [LAW:one-source-of-truth] One computation of SGR codes.
@@ -329,7 +329,7 @@ export class Style {
329
329
  return definition.trim().replace(/\s+/g, " ");
330
330
  }
331
331
  /**
332
- * Parse a space-separated style definition. Cached.
332
+ * Parse a space-separated style definition. Memoized (`Memo`).
333
333
  *
334
334
  * A definition only: `"bold red"` parses, `"repr.number"` does not. Names
335
335
  * belong to a `Theme`, and `Theme.resolve` is where one is looked up.
@@ -338,12 +338,7 @@ export class Style {
338
338
  const normalized = Style.normalize(definition);
339
339
  if (normalized === "" || normalized === "none")
340
340
  return NULL_STYLE;
341
- const cached = styleParseCache.get(normalized);
342
- if (cached)
343
- return cached;
344
- const result = parseStyleDefinition(normalized);
345
- styleParseCache.set(normalized, result);
346
- return result;
341
+ return styleParseMemo.get(normalized, parseStyleDefinition);
347
342
  }
348
343
  }
349
344
  export const NULL_STYLE = new Style();
@@ -368,6 +363,21 @@ export class StyleStack {
368
363
  }
369
364
  // --- Theme ---
370
365
  const STYLE_NAME_RE = /^[a-z][a-z0-9._-]*$/;
366
+ /**
367
+ * `over` added to `base`, the outer style winning as `Style.add` has it. A
368
+ * `Style` base takes the addition now, and so does `""`, the definition that
369
+ * adds nothing; any other string keeps it as a `LayeredStyle` for the render
370
+ * that resolves the string.
371
+ */
372
+ export function layerStyle(base, over) {
373
+ if (base instanceof Style)
374
+ return base.add(over);
375
+ if (base === "")
376
+ return over;
377
+ if (typeof base === "string")
378
+ return { under: base, over };
379
+ return { under: base.under, over: base.over.add(over) };
380
+ }
371
381
  export class Theme {
372
382
  styles;
373
383
  constructor(definitions = {}, options) {
@@ -389,9 +399,10 @@ export class Theme {
389
399
  return this.styles.get(name);
390
400
  }
391
401
  /**
392
- * The style a `string | Style` stands for under this theme: a name this
393
- * theme defines, otherwise a definition for `Style.parse`, which throws
394
- * `StyleSyntaxError` when the string is neither.
402
+ * The style a `TextStyle` stands for under this theme: a name this theme
403
+ * defines, otherwise a definition for `Style.parse`, which throws
404
+ * `StyleSyntaxError` when the string is neither. A `LayeredStyle` is its
405
+ * `under` resolved here with its `over` added on top.
395
406
  *
396
407
  * [LAW:one-source-of-truth] The theme is the one map from names to styles.
397
408
  * The lookup stays outside `Style.parse`'s process-wide cache on purpose:
@@ -401,6 +412,8 @@ export class Theme {
401
412
  resolve(style) {
402
413
  if (style instanceof Style)
403
414
  return style;
415
+ if (typeof style !== "string")
416
+ return this.resolve(style.under).add(style.over);
404
417
  return this.styles.get(style) ?? Style.parse(style);
405
418
  }
406
419
  has(name) {
@@ -545,6 +558,15 @@ function resolveColor(c) {
545
558
  return c;
546
559
  return ColorSpec.parse(c);
547
560
  }
561
+ // A fully transparent background draws nothing over whatever lies beneath it,
562
+ // so it is no background: a style added on top of another keeps that one's,
563
+ // which is what Textual's `#00000000` means. A transparent foreground is not
564
+ // the same, it draws its glyph in whatever lies beneath it — the background,
565
+ // or `SURFACE_BLACK` when there is none — so it stays a colour.
566
+ function resolveBackground(c) {
567
+ const spec = resolveColor(c);
568
+ return spec?.value?.alpha === 0 ? undefined : spec;
569
+ }
548
570
  // --- DEFAULT_STYLES ---
549
571
  // [LAW:one-source-of-truth] Single canonical mapping of semantic names to styles
550
572
  export const DEFAULT_STYLES = {
@@ -585,22 +607,34 @@ export const DEFAULT_STYLES = {
585
607
  "table.cell": NULL_STYLE,
586
608
  "table.title": new Style({ italic: true }),
587
609
  "table.caption": new Style({ italic: true, dim: true }),
588
- // Repr/highlighting
589
- "repr.str": Style.parse("green"),
590
- "repr.number": Style.parse("cyan"),
591
- "repr.bool": Style.parse("italic bright_magenta"),
592
- "repr.none": Style.parse("italic magenta"),
593
- "repr.url": Style.parse("not italic underline bright_blue"),
594
- "repr.uuid": Style.parse("bright_yellow"),
595
- "repr.error": Style.parse("bold red"),
610
+ // Repr/highlighting — Rich 15.0.0's `rich.default_styles`, in its order
611
+ "repr.ellipsis": Style.parse("yellow"),
596
612
  "repr.indent": Style.parse("dim green"),
597
- "repr.attrib_name": Style.parse("yellow"),
598
- "repr.attrib_value": Style.parse("magenta"),
599
- "repr.attrib_equal": Style.parse("bold"),
613
+ "repr.error": Style.parse("bold red"),
614
+ "repr.str": Style.parse("not bold not italic green"),
615
+ "repr.brace": Style.parse("bold"),
616
+ "repr.comma": Style.parse("bold"),
617
+ "repr.ipv4": Style.parse("bold bright_green"),
618
+ "repr.ipv6": Style.parse("bold bright_green"),
619
+ "repr.eui48": Style.parse("bold bright_green"),
620
+ "repr.eui64": Style.parse("bold bright_green"),
600
621
  "repr.tag_start": Style.parse("bold"),
601
- "repr.tag_name": Style.parse("bright_magenta"),
622
+ "repr.tag_name": Style.parse("bold bright_magenta"),
602
623
  "repr.tag_contents": Style.parse("default"),
603
624
  "repr.tag_end": Style.parse("bold"),
625
+ "repr.attrib_name": Style.parse("not italic yellow"),
626
+ "repr.attrib_equal": Style.parse("bold"),
627
+ "repr.attrib_value": Style.parse("not italic magenta"),
628
+ "repr.number": Style.parse("bold not italic cyan"),
629
+ "repr.number_complex": Style.parse("bold not italic cyan"),
630
+ "repr.bool_true": Style.parse("italic bright_green"),
631
+ "repr.bool_false": Style.parse("italic bright_red"),
632
+ "repr.none": Style.parse("italic magenta"),
633
+ "repr.url": Style.parse("not bold not italic underline bright_blue"),
634
+ "repr.uuid": Style.parse("not bold bright_yellow"),
635
+ "repr.call": Style.parse("bold magenta"),
636
+ "repr.path": Style.parse("magenta"),
637
+ "repr.filename": Style.parse("bright_magenta"),
604
638
  // Log
605
639
  "log.time": Style.parse("cyan dim"),
606
640
  "log.message": NULL_STYLE,
@@ -608,8 +642,10 @@ export const DEFAULT_STYLES = {
608
642
  "log.line_no": Style.parse("cyan"),
609
643
  "log.level": NULL_STYLE,
610
644
  // Rule
611
- "rule.line": Style.parse("green"),
612
- "rule.text": Style.parse("bold"),
645
+ "rule.line": Style.parse("bright_green"),
646
+ "rule.text": NULL_STYLE,
647
+ // Strip
648
+ "strip.separator": Style.parse("bright_black"),
613
649
  // JSON
614
650
  "json.brace": Style.parse("bold"),
615
651
  "json.bool_true": Style.parse("italic bright_green"),
@@ -618,20 +654,34 @@ export const DEFAULT_STYLES = {
618
654
  "json.null": Style.parse("italic magenta"),
619
655
  "json.number": Style.parse("bold not italic cyan"),
620
656
  "json.str": Style.parse("not bold not italic green"),
657
+ // Syntax
658
+ "syntax.keyword": Style.parse("bold magenta"),
659
+ "syntax.constant": Style.parse("italic bright_magenta"),
660
+ "syntax.string": Style.parse("green"),
661
+ "syntax.number": Style.parse("cyan"),
662
+ "syntax.comment": Style.parse("dim italic"),
663
+ "syntax.line_number": Style.parse("dim"),
664
+ // Ink and ground both from the fixed 256-colour greys: the terminal theme's
665
+ // own foreground is dark on a light theme and would vanish on grey27. At 16
666
+ // colours `Syntax` draws it without the pair (`groundedStyle`).
667
+ "syntax.line_number.highlight": Style.parse("bold grey93 on grey27"),
621
668
  // Markdown
622
669
  "markdown.h1": Style.parse("bold underline"),
623
670
  "markdown.h2": Style.parse("bold"),
624
671
  "markdown.h3": Style.parse("bold dim"),
625
672
  "markdown.h4": Style.parse("bold dim italic"),
626
- "markdown.code": Style.parse("cyan on grey11"),
673
+ // A fixed cyan, not the theme's: `cyan` is dark enough on some themes to
674
+ // sink into grey11. Bold, as Rich's is: at 16 colours a renderable draws it
675
+ // without its pair (`groundedStyle`), and bold is what still marks code.
676
+ "markdown.code": Style.parse("bold dark_turquoise on grey11"),
627
677
  "markdown.hr": Style.parse("yellow"),
628
678
  "markdown.link": Style.parse("bright_blue"),
629
679
  "markdown.link_url": Style.parse("blue"),
630
680
  // Progress
631
681
  "progress.description": NULL_STYLE,
632
- "progress.percentage": Style.parse("cyan"),
682
+ "progress.percentage": Style.parse("magenta"),
633
683
  "progress.remaining": Style.parse("cyan"),
634
- "progress.elapsed": Style.parse("cyan"),
684
+ "progress.elapsed": Style.parse("yellow"),
635
685
  "progress.spinner": Style.parse("green"),
636
686
  "progress.download": Style.parse("green"),
637
687
  "progress.filesize": Style.parse("green"),
@@ -639,9 +689,9 @@ export const DEFAULT_STYLES = {
639
689
  "progress.data.speed": Style.parse("red"),
640
690
  // Bar
641
691
  "bar.back": Style.parse("grey23"),
642
- "bar.complete": Style.parse("magenta"),
643
- "bar.finished": Style.parse("green"),
644
- "bar.pulse": Style.parse("magenta"),
692
+ "bar.complete": Style.parse("rgb(249,38,114)"),
693
+ "bar.finished": Style.parse("rgb(114,156,31)"),
694
+ "bar.pulse": Style.parse("rgb(249,38,114)"),
645
695
  // Scrollbar
646
696
  "scrollbar.thumb": NULL_STYLE,
647
697
  "scrollbar.track": Style.parse("grey37"),
@@ -652,9 +702,11 @@ export const DEFAULT_STYLES = {
652
702
  "status.spinner": Style.parse("green"),
653
703
  "status.message": NULL_STYLE,
654
704
  // Prompt
655
- "prompt": Style.parse("bold"),
656
- "prompt.choices": Style.parse("magenta"),
657
- "prompt.default": Style.parse("cyan"),
705
+ "prompt": NULL_STYLE,
706
+ "prompt.choices": Style.parse("bold magenta"),
707
+ "prompt.default": Style.parse("bold cyan"),
708
+ "prompt.invalid": Style.parse("red"),
709
+ "prompt.invalid.choice": Style.parse("red"),
658
710
  // Inspect
659
711
  "inspect.attr": Style.parse("yellow italic"),
660
712
  "inspect.attr.dunder": Style.parse("yellow italic dim"),
@@ -677,9 +729,22 @@ export const DEFAULT_STYLES = {
677
729
  // Pretty
678
730
  "pretty": NULL_STYLE,
679
731
  // ISO8601
680
- "iso8601.date": Style.parse("cyan"),
681
- "iso8601.time": Style.parse("cyan"),
682
- "iso8601.timezone": Style.parse("bright_blue"),
732
+ "iso8601.date": Style.parse("blue"),
733
+ "iso8601.time": Style.parse("magenta"),
734
+ "iso8601.timezone": Style.parse("yellow"),
735
+ // The parts ISO8601Highlighter lays inside a date or time. Rich's theme names
736
+ // none of them, so they draw nothing; they are here so a theme can set them
737
+ // and so none reaches `onStyleError` as an unknown name.
738
+ "iso8601.year": NULL_STYLE,
739
+ "iso8601.month": NULL_STYLE,
740
+ "iso8601.day": NULL_STYLE,
741
+ "iso8601.week": NULL_STYLE,
742
+ "iso8601.hour": NULL_STYLE,
743
+ "iso8601.minute": NULL_STYLE,
744
+ "iso8601.second": NULL_STYLE,
745
+ "iso8601.frac": NULL_STYLE,
746
+ "iso8601.ms": NULL_STYLE,
747
+ "iso8601.hyphen": NULL_STYLE,
683
748
  };
684
749
  /**
685
750
  * The theme a render resolves names against when nothing supplied one — what
@@ -2,14 +2,21 @@
2
2
  * RichText — styled text with spans. The primary text type for the library.
3
3
  */
4
4
  import { Segment } from "./segment.js";
5
- import { Style } from "./style.js";
5
+ import { Style, type TextStyle } from "./style.js";
6
6
  import type { Renderable, Measurable, OverflowMethod, RenderOptions } from "./protocol.js";
7
7
  export declare function stripControlChars(text: string): string;
8
+ /**
9
+ * The style a stored `TextStyle` stands for in this render.
10
+ *
11
+ * A parsed string can carry a link, so the result is sanitized on the way out
12
+ * as well.
13
+ */
14
+ export declare function resolveStyle(options: RenderOptions, style: TextStyle): Style;
8
15
  export declare class Span {
9
16
  readonly start: number;
10
17
  readonly end: number;
11
- readonly style: string | Style;
12
- constructor(start: number, end: number, style: string | Style);
18
+ readonly style: TextStyle;
19
+ constructor(start: number, end: number, style: TextStyle);
13
20
  get hasLength(): boolean;
14
21
  toString(): string;
15
22
  split(offset: number): [Span, Span | undefined];
@@ -18,7 +25,7 @@ export declare class Span {
18
25
  extend(count: number): Span;
19
26
  }
20
27
  export interface RichTextOptions {
21
- style?: string | Style;
28
+ style?: TextStyle;
22
29
  justify?: "left" | "center" | "right" | "full";
23
30
  overflow?: OverflowMethod;
24
31
  end?: string;
@@ -38,11 +45,19 @@ export declare class RichText implements Renderable, Measurable {
38
45
  get plain(): string;
39
46
  set plain(value: string);
40
47
  get length(): number;
48
+ /**
49
+ * The cells of the plain text with each tab widened to its stop counted from
50
+ * this text's own column 0, as `render` widens it — so it is the drawn width
51
+ * of a one-line text set at a stop. A deliberate departure from Rich, whose
52
+ * `Text.cell_len` counts a tab as no cells, so everything sized by it — a
53
+ * truncation, an alignment, a header's remaining width — decided on a width
54
+ * no render draws.
55
+ */
41
56
  get cellLength(): number;
42
57
  get hasContent(): boolean;
43
- /** The base style every span layers over: a `Style`, or a name resolved at render. */
44
- get style(): string | Style;
45
- set style(value: string | Style);
58
+ /** The base style every span layers over, resolved at render unless it is a `Style`. */
59
+ get style(): TextStyle;
60
+ set style(value: TextStyle);
46
61
  get justify(): "left" | "center" | "right" | "full" | undefined;
47
62
  set justify(value: "left" | "center" | "right" | "full" | undefined);
48
63
  get overflow(): OverflowMethod | undefined;
@@ -79,7 +94,7 @@ export declare class RichText implements Renderable, Measurable {
79
94
  * drawn, and a style name draws as whatever the render's theme says.
80
95
  */
81
96
  edgeStyle(side: "left" | "right", options: RenderOptions): Style;
82
- append(content: string | RichText, style?: string | Style): this;
97
+ append(content: string | RichText, style?: TextStyle): this;
83
98
  contains(needle: string | RichText): boolean;
84
99
  at(index: number): RichText;
85
100
  slice(start?: number, end?: number): RichText;
@@ -89,9 +104,9 @@ export declare class RichText implements Renderable, Measurable {
89
104
  * is admitted as given.
90
105
  */
91
106
  private _addSpan;
92
- stylize(style: string | Style, start?: number, end?: number): this;
93
- highlightRegex(pattern: RegExp, style?: string | Style): number;
94
- highlightWords(words: string[], style: string | Style, options?: {
107
+ stylize(style: TextStyle, start?: number, end?: number): this;
108
+ highlightRegex(pattern: RegExp, style?: TextStyle): number;
109
+ highlightWords(words: string[], style: TextStyle, options?: {
95
110
  caseSensitive?: boolean;
96
111
  }): number;
97
112
  copy(): RichText;
@@ -100,6 +115,12 @@ export declare class RichText implements Renderable, Measurable {
100
115
  divide(offsets: number[]): RichText[];
101
116
  rstrip(): this;
102
117
  pad(count: number, char?: string): this;
118
+ /**
119
+ * Each tab widened to the next tab stop, in place, as Rich's
120
+ * `Text.expand_tabs` widens it: spans move with the characters they style, so
121
+ * the text measures what it will draw.
122
+ */
123
+ expandTabs(): this;
103
124
  padLeft(count: number, char?: string): this;
104
125
  padRight(count: number, char?: string): this;
105
126
  setLength(length: number): this;
@@ -124,6 +145,10 @@ export declare class RichText implements Renderable, Measurable {
124
145
  * styling; the marker (if any) is inserted as plain text with no span.
125
146
  * Use `stylize(...)` on the result to color the marker if needed.
126
147
  *
148
+ * Text that fits comes back untouched. Text that is cut has its tabs widened
149
+ * to their stops first, as `expandTabs` widens them, so the width cut to is
150
+ * the width drawn.
151
+ *
127
152
  * [LAW:dataflow-not-control-flow] mode/marker/width all flow as values;
128
153
  * the walk is the same shape regardless. No "if truncated then rebuild"
129
154
  * branch \u2014 the unchanged path just early-returns when content fits.
@@ -136,11 +161,11 @@ export declare class RichText implements Renderable, Measurable {
136
161
  private _cropLeftTo;
137
162
  align(justify: "left" | "center" | "right", width: number): this;
138
163
  removeSuffix(suffix: string): this;
139
- appendTokens(tokens: Array<[string, (string | Style)?]>): this;
140
- static assemble(parts: Array<string | [string, (string | Style)?] | RichText>, options?: {
141
- style?: string | Style;
164
+ appendTokens(tokens: Array<[string, TextStyle?]>): this;
165
+ static assemble(parts: Array<string | [string, TextStyle?] | RichText>, options?: {
166
+ style?: TextStyle;
142
167
  }): RichText;
143
- static styled(text: string, style: string | Style): RichText;
168
+ static styled(text: string, style: TextStyle): RichText;
144
169
  /**
145
170
  * Concatenate a sequence of `RichText` fragments into a single `RichText`,
146
171
  * flattening each fragment's wrapping `style` onto a span over that
@@ -165,7 +190,6 @@ export declare class RichText implements Renderable, Measurable {
165
190
  minimum: number;
166
191
  maximum: number;
167
192
  };
168
- private _expandTabs;
169
193
  /**
170
194
  * The rendered text cut at every span edge, each piece carrying the base
171
195
  * style plus every span covering it.
@@ -218,6 +242,9 @@ export declare class RichText implements Renderable, Measurable {
218
242
  * `undefined` is not `"left"`: it is Rich's `"default"`, which places the
219
243
  * line without padding it at all. That distinction is what lets a soft-wrapped
220
244
  * `Console.print` leave its lines at their natural width.
245
+ *
246
+ * The padding is drawn in the text's base style, as the reference pads
247
+ * inside the `Text` it justifies: a title "on red" fills its row in red.
221
248
  */
222
249
  private _justifyLine;
223
250
  /**