@promptctl/rich-js 0.18.1 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +9 -7
  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 +98 -18
  9. package/dist/core/color.js +331 -144
  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/osc8.d.ts +6 -6
  33. package/dist/core/osc8.js +9 -21
  34. package/dist/core/paint.d.ts +107 -0
  35. package/dist/core/paint.js +150 -0
  36. package/dist/core/place.d.ts +1 -1
  37. package/dist/core/place.js +4 -6
  38. package/dist/core/pretty.d.ts +105 -2
  39. package/dist/core/pretty.js +527 -97
  40. package/dist/core/protocol.d.ts +41 -3
  41. package/dist/core/protocol.js +20 -0
  42. package/dist/core/render.d.ts +33 -30
  43. package/dist/core/render.js +43 -83
  44. package/dist/core/segment.d.ts +6 -5
  45. package/dist/core/segment.js +11 -15
  46. package/dist/core/strip.d.ts +13 -2
  47. package/dist/core/strip.js +44 -23
  48. package/dist/core/style.d.ts +27 -7
  49. package/dist/core/style.js +97 -34
  50. package/dist/core/text.d.ts +43 -16
  51. package/dist/core/text.js +180 -59
  52. package/dist/core/wrap.d.ts +5 -0
  53. package/dist/core/wrap.js +16 -3
  54. package/dist/host/app.d.ts +31 -19
  55. package/dist/host/app.js +90 -60
  56. package/dist/host/index.d.ts +2 -1
  57. package/dist/host/terminal-host.d.ts +3 -2
  58. package/dist/index.d.ts +17 -10
  59. package/dist/index.js +11 -4
  60. package/dist/node/prompt.d.ts +13 -0
  61. package/dist/node/prompt.js +30 -9
  62. package/dist/node/save.d.ts +4 -3
  63. package/dist/node/save.js +6 -3
  64. package/dist/node/terminal-host.d.ts +3 -2
  65. package/dist/node/traceback.d.ts +2 -1
  66. package/dist/node/traceback.js +3 -39
  67. package/dist/renderables/align.js +2 -9
  68. package/dist/renderables/columns.d.ts +45 -29
  69. package/dist/renderables/columns.js +142 -103
  70. package/dist/renderables/constrain.js +6 -12
  71. package/dist/renderables/effect.d.ts +98 -0
  72. package/dist/renderables/effect.js +160 -0
  73. package/dist/renderables/embed.d.ts +87 -30
  74. package/dist/renderables/embed.js +134 -45
  75. package/dist/renderables/group.d.ts +6 -3
  76. package/dist/renderables/group.js +5 -0
  77. package/dist/renderables/layout.d.ts +6 -23
  78. package/dist/renderables/layout.js +24 -113
  79. package/dist/renderables/live.d.ts +40 -16
  80. package/dist/renderables/live.js +96 -83
  81. package/dist/renderables/markdown.d.ts +16 -2
  82. package/dist/renderables/markdown.js +521 -118
  83. package/dist/renderables/padding.d.ts +22 -1
  84. package/dist/renderables/padding.js +30 -24
  85. package/dist/renderables/panel.d.ts +31 -33
  86. package/dist/renderables/panel.js +137 -141
  87. package/dist/renderables/progress.d.ts +104 -16
  88. package/dist/renderables/progress.js +205 -81
  89. package/dist/renderables/progressBar.d.ts +2 -2
  90. package/dist/renderables/progressBar.js +30 -19
  91. package/dist/renderables/prompt.d.ts +37 -15
  92. package/dist/renderables/prompt.js +125 -85
  93. package/dist/renderables/ratio.d.ts +123 -0
  94. package/dist/renderables/ratio.js +213 -0
  95. package/dist/renderables/rule.d.ts +1 -0
  96. package/dist/renderables/rule.js +44 -48
  97. package/dist/renderables/spinner.d.ts +28 -2
  98. package/dist/renderables/spinner.js +52 -19
  99. package/dist/renderables/status.d.ts +13 -7
  100. package/dist/renderables/status.js +15 -29
  101. package/dist/renderables/syntax.d.ts +37 -7
  102. package/dist/renderables/syntax.js +134 -83
  103. package/dist/renderables/table.d.ts +58 -20
  104. package/dist/renderables/table.js +370 -192
  105. package/dist/renderables/traceback.d.ts +5 -4
  106. package/dist/renderables/traceback.js +239 -68
  107. package/dist/renderables/tree.d.ts +10 -2
  108. package/dist/renderables/tree.js +61 -34
  109. package/dist/renderables/viewport.js +2 -4
  110. package/dist/template-bindings/color-funcs.d.ts +31 -9
  111. package/dist/template-bindings/color-funcs.js +40 -14
  112. package/dist/template-bindings/helpers.d.ts +4 -2
  113. package/dist/template-bindings/helpers.js +5 -20
  114. package/dist/template-bindings/index.d.ts +29 -17
  115. package/dist/template-bindings/index.js +36 -20
  116. package/dist/template-bindings/palette-funcs.d.ts +3 -1
  117. package/dist/template-bindings/palette-funcs.js +11 -7
  118. package/dist/template-bindings/style-funcs.js +4 -2
  119. package/dist/themes/buildPalette.d.ts +24 -3
  120. package/dist/themes/buildPalette.js +52 -8
  121. package/dist/themes/colorMath.d.ts +29 -17
  122. package/dist/themes/colorMath.js +74 -48
  123. package/dist/themes/colorRef.d.ts +2 -17
  124. package/dist/themes/colorRef.js +13 -31
  125. package/dist/themes/palette.d.ts +24 -0
  126. package/dist/themes/palette.js +46 -3
  127. package/dist/themes/ramp.d.ts +21 -34
  128. package/dist/themes/ramp.js +23 -42
  129. package/dist/themes/registry.js +39 -28
  130. package/dist/widgets/button.d.ts +2 -6
  131. package/dist/widgets/button.js +9 -40
  132. package/dist/widgets/checkbox.d.ts +2 -5
  133. package/dist/widgets/checkbox.js +9 -31
  134. package/dist/widgets/dropdown.d.ts +2 -5
  135. package/dist/widgets/dropdown.js +14 -48
  136. package/dist/widgets/ink.d.ts +22 -0
  137. package/dist/widgets/ink.js +31 -0
  138. package/dist/widgets/slider.d.ts +2 -5
  139. package/dist/widgets/slider.js +11 -34
  140. package/dist/widgets/text-input.d.ts +19 -10
  141. package/dist/widgets/text-input.js +156 -147
  142. package/dist/widgets/themed-widget.d.ts +20 -0
  143. package/dist/widgets/themed-widget.js +89 -0
  144. package/dist/widgets/toggle.d.ts +2 -5
  145. package/dist/widgets/toggle.js +8 -31
  146. package/dist/widgets/widget-app.d.ts +2 -0
  147. package/dist/widgets/widget-app.js +13 -6
  148. package/dist/widgets/widget-base.d.ts +2 -0
  149. package/dist/widgets/widget-base.js +9 -2
  150. package/package.json +11 -1
@@ -24,10 +24,10 @@ export declare class ReprHighlighter extends RegexHighlighter {
24
24
  }
25
25
  export declare class JSONHighlighter extends RegexHighlighter {
26
26
  static baseStyle: string;
27
- static highlights: string[];
27
+ static highlights: RegExp[];
28
28
  highlight(text: RichText): void;
29
29
  }
30
30
  export declare class ISO8601Highlighter extends RegexHighlighter {
31
31
  static baseStyle: string;
32
- static highlights: RegExp[];
32
+ static highlights: string[];
33
33
  }
@@ -31,71 +31,100 @@ export class RegexHighlighter extends Highlighter {
31
31
  // Literal mode: "bold red" → applied directly to every match
32
32
  const isNamespace = baseStyle.endsWith(".");
33
33
  for (const pattern of ctor.highlights) {
34
- const re = pattern instanceof RegExp
35
- ? new RegExp(pattern.source, pattern.flags.includes("g") ? pattern.flags : pattern.flags + "g")
36
- : new RegExp(pattern, "g");
37
- let match;
38
- while ((match = re.exec(text.plain)) !== null) {
39
- if (match[0].length === 0) {
40
- re.lastIndex++;
41
- continue;
42
- }
43
- if (match.groups) {
44
- let searchFrom = 0;
45
- for (const [groupName, groupValue] of Object.entries(match.groups)) {
46
- if (groupValue !== undefined) {
47
- const posInMatch = match[0].indexOf(groupValue, searchFrom);
48
- if (posInMatch >= 0) {
49
- const start = match.index + posInMatch;
50
- const style = isNamespace
51
- ? `${baseStyle}${groupName}`
52
- : baseStyle || groupName;
53
- text.stylize(style, start, start + groupValue.length);
54
- searchFrom = posInMatch + groupValue.length;
55
- }
56
- }
57
- }
34
+ // `d` reports where each group matched, as Python's `match.span(name)`
35
+ // does; searching the match for the group's text finds the first copy
36
+ // of it, which is not always the one the group captured.
37
+ const source = pattern instanceof RegExp ? pattern.source : pattern;
38
+ const flags = new Set([...(pattern instanceof RegExp ? pattern.flags : ""), "g", "d"]);
39
+ for (const match of text.plain.matchAll(new RegExp(source, [...flags].join("")))) {
40
+ if (match.indices === undefined)
41
+ throw new Error("a match of a `d`-flag pattern carries indices");
42
+ // Group definition order, as Rich's `groupdict()`: a later group's span
43
+ // lands on top of an earlier one's.
44
+ for (const [groupName, span] of Object.entries(match.indices.groups ?? {})) {
45
+ if (span === undefined || span[1] <= span[0])
46
+ continue;
47
+ const style = isNamespace ? `${baseStyle}${groupName}` : baseStyle || groupName;
48
+ text.stylize(style, span[0], span[1]);
58
49
  }
59
50
  }
60
51
  }
61
52
  }
62
53
  }
54
+ // --- Python's regex classes ---
55
+ // Rich compiles its patterns on a `str`, where Python's `\w`, `\b` and `\d` are
56
+ // Unicode-aware; JavaScript's are ASCII even under `u`, so `café=1` would lose
57
+ // its attribute name and `étrue` would gain a `true`. These spell Python's for
58
+ // the `u` flag for ReprHighlighter and JSONHighlighter. `.` is spelled `[^\n]`
59
+ // because Python's dot stops only at `\n`, JavaScript's at `\r`, U+2028 and
60
+ // U+2029 too.
61
+ const W = String.raw `\p{L}\p{N}_`;
62
+ const WB = String.raw `(?:(?<=[${W}])(?![${W}])|(?<![${W}])(?=[${W}]))`;
63
+ const NWB = String.raw `(?:(?<=[${W}])(?=[${W}])|(?<![${W}])(?![${W}]))`;
64
+ const D = String.raw `\p{Nd}`;
65
+ // Rich's `[0-9]+\.?[0-9]*`, the digits of a number with an optional fraction,
66
+ // spelled so a digit run has one way to split. Rich's spelling can hand any
67
+ // prefix of a run to `[0-9]+` and the rest to `[0-9]*`, and a run that fails
68
+ // the boundary after it is retried at every split: quadratic in its length.
69
+ // Both spellings match the same strings and try them in the same order.
70
+ const DECIMAL = String.raw `[0-9]+(?:\.[0-9]*)?`;
63
71
  // --- ReprHighlighter ---
72
+ // Rich 15.0.0's patterns.
64
73
  // [LAW:one-type-per-behavior] All repr patterns use the same RegexHighlighter mechanism
65
74
  export class ReprHighlighter extends RegexHighlighter {
66
75
  static baseStyle = "repr.";
67
76
  static highlights = [
68
- // URLs
69
- /(?<url>https?:\/\/[^\s<>"']+)/g,
70
- // UUIDs
71
- /(?<uuid>[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/gi,
72
- // Quoted strings
73
- /(?<str>'[^']*'|"[^"]*")/g,
74
- // Booleans
75
- /(?<bool>\btrue\b|\bfalse\b)/g,
76
- // None/null/undefined
77
- /(?<none>\bnull\b|\bundefined\b|\bNone\b)/g,
78
- // Numbers (integers and floats)
79
- /(?<number>(?<!\w)-?(?:0x[0-9a-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)(?!\w))/gi,
77
+ // `tag_contents` runs to the text's last `>`, so only the text's first `<`
78
+ // can open a tag; the lookbehind starts the match there and nowhere else,
79
+ // where Rich retries every later `<` and rescans to the end each time. The
80
+ // lookahead asks once whether any `>` follows; without it, a `<` before a
81
+ // long name with no `>` rescans to the end for every length of the name.
82
+ new RegExp(String.raw `(?<tag_start><)(?<=^[^<]*<)(?=[^]*>)(?<tag_name>[\-${W}.:|]*)(?<tag_contents>[^]*)(?<tag_end>>)`, "u"),
83
+ new RegExp(String.raw `(?<attrib_name>[${W}]{1,50})=(?<attrib_value>"?[${W}]+"?)?`, "u"),
84
+ new RegExp(String.raw `(?<brace>[\][{}()])`, "u"),
85
+ // [LAW:dataflow-not-control-flow] One alternation, scanned once, as Rich's
86
+ // `_combine_regex` joins it: where two could match, the earlier claims it.
87
+ new RegExp([
88
+ String.raw `(?<ipv4>[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})`,
89
+ String.raw `(?<ipv6>([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4})`,
90
+ String.raw `(?<eui64>(?:[0-9A-Fa-f]{1,2}-){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){7}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){3}[0-9A-Fa-f]{4})`,
91
+ String.raw `(?<eui48>(?:[0-9A-Fa-f]{1,2}-){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{1,2}:){5}[0-9A-Fa-f]{1,2}|(?:[0-9A-Fa-f]{4}\.){2}[0-9A-Fa-f]{4})`,
92
+ String.raw `(?<uuid>[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})`,
93
+ // Departs from Rich: a call name starts a word, so the run is scanned
94
+ // for its `(` once, not again from each of its characters. Rich also
95
+ // styles a name that starts where another match ended mid-word, the
96
+ // `foo` of `aa-bb-cc-dd-ee-fffoo(`; this leaves it to the patterns
97
+ // after this one, so it is plain or, as `true` in `-1.true(`, theirs.
98
+ String.raw `(?<call>(?<![${W}.])[${W}.]*?)\(`,
99
+ // JavaScript's `true`, `false`, `null` and `undefined` beside Python's
100
+ // names: `Pretty` draws JavaScript values through this highlighter.
101
+ String.raw `${WB}(?<bool_true>True|true)${WB}|${WB}(?<bool_false>False|false)${WB}|${WB}(?<none>None|null|undefined)${WB}`,
102
+ String.raw `(?<ellipsis>\.\.\.)`,
103
+ String.raw `(?<number_complex>(?<![${W}])(?:-?${DECIMAL}(?:e[\-+]?${D}+?)?)(?:[\-+](?:${DECIMAL}(?:e[\-+]?${D}+)?))?j)`,
104
+ String.raw `(?<number>(?<![${W}])-?${DECIMAL}(e[\-+]?${D}+?)?${WB}|0x[0-9a-fA-F]*)`,
105
+ String.raw `(?<path>${NWB}(\/[\-${W}._+]+)*\/)(?<filename>[\-${W}._+]*)?`,
106
+ String.raw `(?<![\\${W}])(?<str>b?'''[^\n]*?(?<!\\)'''|b?'[^\n]*?(?<!\\)'|b?"""[^\n]*?(?<!\\)"""|b?"[^\n]*?(?<!\\)")`,
107
+ String.raw `(?<url>(file|https|http|ws|wss):\/\/[\-0-9a-zA-Z$_+!\x60(),.?\/;:&=%#~@]*)`,
108
+ ].join("|"), "u"),
80
109
  ];
81
110
  }
82
111
  // --- JSONHighlighter ---
83
- // A JSON string as Python Rich 9d8f9a3 matches one, `b` bytes prefix included:
84
- // an opening quote with no backslash or word character before it, through the
112
+ // A JSON string as Rich 15.0.0 matches one, `b` bytes prefix included: an
113
+ // opening quote with no backslash or word character before it, through the
85
114
  // first quote with no backslash before it, so an escaped quote stays inside.
86
- const JSON_STR = String.raw `(?<![\\\w])(?<str>b?".*?(?<!\\)")`;
115
+ const JSON_STR = String.raw `(?<![\\${W}])(?<str>b?"[^\n]*?(?<!\\)")`;
87
116
  export class JSONHighlighter extends RegexHighlighter {
88
117
  static baseStyle = "json.";
89
118
  // [LAW:dataflow-not-control-flow] One alternation, scanned once, as Rich's
90
119
  // `_combine_regex` joins it. A token claims its characters where the scan
91
120
  // meets it, so the `true` and `12` inside `"true 12"` belong to the string.
92
121
  static highlights = [
93
- [
122
+ new RegExp([
94
123
  String.raw `(?<brace>[\{\[\(\)\]\}])`,
95
- String.raw `\b(?<bool_true>true)\b|\b(?<bool_false>false)\b|\b(?<null>null)\b`,
96
- String.raw `(?<number>(?<!\w)\-?[0-9]+\.?[0-9]*(e[\-\+]?\d+?)?\b|0x[0-9a-fA-F]*)`,
124
+ String.raw `${WB}(?<bool_true>true)${WB}|${WB}(?<bool_false>false)${WB}|${WB}(?<null>null)${WB}`,
125
+ String.raw `(?<number>(?<![${W}])-?${DECIMAL}(e[\-+]?${D}+?)?${WB}|0x[0-9a-fA-F]*)`,
97
126
  JSON_STR,
98
- ].join("|"),
127
+ ].join("|"), "u"),
99
128
  ];
100
129
  // A string followed by a colon is also a key. Its `json.key` span comes after
101
130
  // its `json.str` span, so the key style lands on top. Each string is found on
@@ -105,7 +134,7 @@ export class JSONHighlighter extends RegexHighlighter {
105
134
  highlight(text) {
106
135
  super.highlight(text);
107
136
  const colon = /[ \n\r\t]*:/y;
108
- for (const { index, 0: str } of text.plain.matchAll(new RegExp(JSON_STR, "g"))) {
137
+ for (const { index, 0: str } of text.plain.matchAll(new RegExp(JSON_STR, "gu"))) {
109
138
  const end = index + str.length;
110
139
  colon.lastIndex = end;
111
140
  if (colon.test(text.plain))
@@ -114,11 +143,48 @@ export class JSONHighlighter extends RegexHighlighter {
114
143
  }
115
144
  }
116
145
  // --- ISO8601Highlighter ---
146
+ // Rich 15.0.0's patterns, after the Regular Expressions Cookbook recipes it
147
+ // cites. Each matches a whole string that is one ISO 8601 value, never a value
148
+ // inside other text. Python's `$` also matches before a final `\n`, which
149
+ // JavaScript's does not; `END` is Python's.
150
+ const END = String.raw `(?=\n?$)`;
151
+ const YEAR = String.raw `(?<year>[0-9]{4})`;
152
+ const MONTH = String.raw `(?<month>1[0-2]|0[1-9])`;
153
+ const DAY = String.raw `(?<day>3[01]|0[1-9]|[12][0-9])`;
154
+ const HOUR = String.raw `(?<hour>2[0-3]|[01][0-9])`;
155
+ const MINUTE = String.raw `(?<minute>[0-5][0-9])`;
156
+ const SECOND = String.raw `(?<second>[0-5][0-9])`;
157
+ const WEEK = String.raw `(?<week>5[0-3]|[1-4][0-9]|0[1-9])`;
158
+ const TZ_HOUR = String.raw `[+-](?:2[0-3]|[01][0-9])`;
159
+ const XSD_DATE = String.raw `(?<date>(?<year>-?(?:[1-9][0-9]*)?[0-9]{4})-${MONTH}-${DAY})`;
160
+ const XSD_TZ = String.raw `(?<timezone>Z|${TZ_HOUR}:[0-5][0-9])?`;
161
+ // The cookbook's designator, whose minutes and their colon are both optional.
162
+ const TZ = String.raw `(?<timezone>Z|${TZ_HOUR}(?::?(?:[0-5][0-9]))?)`;
163
+ const COMPACT_TIME = `(?<time>${HOUR}${MINUTE}${SECOND})`;
117
164
  export class ISO8601Highlighter extends RegexHighlighter {
118
165
  static baseStyle = "iso8601.";
119
166
  static highlights = [
120
- /(?<date>\d{4}-\d{2}-\d{2})/g,
121
- /(?<time>\d{2}:\d{2}:\d{2}(?:\.\d+)?)/g,
122
- /(?<timezone>[+-]\d{2}:\d{2}|Z)/g,
167
+ // Dates
168
+ `^${YEAR}-${MONTH}${END}`,
169
+ `^(?<date>${YEAR}${MONTH}${DAY})${END}`,
170
+ String.raw `^(?<date>${YEAR}-?(?<day>36[0-6]|3[0-5][0-9]|[12][0-9]{2}|0[1-9][0-9]|00[1-9]))${END}`,
171
+ // Weeks
172
+ `^(?<date>${YEAR}-?W${WEEK})${END}`,
173
+ `^(?<date>${YEAR}-?W${WEEK}-?(?<day>[1-7]))${END}`,
174
+ // Times
175
+ `^(?<time>${HOUR}:?${MINUTE})${END}`,
176
+ `^${COMPACT_TIME}${END}`,
177
+ `^${TZ}${END}`,
178
+ `^${COMPACT_TIME}${TZ}${END}`,
179
+ // Date and time. Rich writes this as one pattern whose `-` and `:`
180
+ // separators are all present or all absent, keyed on a Python conditional
181
+ // group JavaScript lacks; it is the two spellings here, adjacent, so the
182
+ // one that matches lays its spans where Rich's single pattern would.
183
+ `^(?<date>${YEAR}(?<hyphen>-)${MONTH}-${DAY}) (?<time>${HOUR}:${MINUTE}:${SECOND})${END}`,
184
+ `^(?<date>${YEAR}${MONTH}${DAY}) ${COMPACT_TIME}${END}`,
185
+ // XML Schema date, time and dateTime
186
+ `^${XSD_DATE}${XSD_TZ}${END}`,
187
+ String.raw `^(?<time>${HOUR}:${MINUTE}:${SECOND}(?<frac>\.[0-9]+)?)${XSD_TZ}${END}`,
188
+ String.raw `^${XSD_DATE}T(?<time>${HOUR}:${MINUTE}:${SECOND}(?<ms>\.[0-9]+)?)${XSD_TZ}${END}`,
123
189
  ];
124
190
  }
package/dist/core/json.js CHANGED
@@ -38,7 +38,7 @@ export class JSONRenderable {
38
38
  }
39
39
  : undefined;
40
40
  const jsonStr = JSON.stringify(data, replacer, indent);
41
- const text = new RichText(jsonStr, { end: "" });
41
+ const text = new RichText(jsonStr);
42
42
  if (doHighlight) {
43
43
  highlighter.highlight(text);
44
44
  }
@@ -5,8 +5,8 @@
5
5
  * Plugin tags ([LAW:locality-or-seam]): a `MarkupRegistry` lets consumers
6
6
  * register tag handlers without forking the parser. When the parser sees
7
7
  * `[name attrs...]inner[/name]` and `name` is registered, it parses attrs,
8
- * recursively renders the inner markup as a child Renderable, and calls the
9
- * handler — splicing the handler's returned Renderable into the output. The
8
+ * renders the inner markup as the child `RichText`, and calls the handler —
9
+ * splicing the `RichText` it returns into the output. The
10
10
  * built-in style dialect and the plugin dialect are routed by the registry,
11
11
  * which is the single trust boundary between them.
12
12
  *
@@ -14,10 +14,12 @@
14
14
  * (`[bold]a[italic]b[/bold]c[/italic]`) because a style is an annotation and
15
15
  * annotations may overlap freely; a plugin tag is a replacement whose handler
16
16
  * takes one contiguous `inner`, so an overlapping pair has no slice to hand it
17
- * and is rejected with a `MarkupSyntaxError`.
17
+ * and is rejected with a `MarkupSyntaxError`. For the same reason a style tag
18
+ * may not open on one side of a plugin tag and close on the other.
18
19
  */
19
20
  import { Style } from "./style.js";
20
21
  import { RichText } from "./text.js";
22
+ import type { RenderOptions as DrawOptions } from "./protocol.js";
21
23
  export declare class Tag {
22
24
  readonly name: string;
23
25
  readonly parameters: string | undefined;
@@ -54,8 +56,7 @@ export declare class MarkupSyntaxError extends MarkupError {
54
56
  /** 1-based column of `offset` within its line, in UTF-16 code units. */
55
57
  readonly column: number;
56
58
  /**
57
- * The opening tags still open at `offset`, outermost first, as written. For
58
- * overlapping plugin tags, only plugin tags are named.
59
+ * The opening tags still open at `offset`, outermost first, as written.
59
60
  */
60
61
  readonly openTags: readonly string[];
61
62
  constructor(reason: string, markup: string, offset: number, openTags: readonly string[]);
@@ -113,7 +114,27 @@ export interface RenderMarkupOptions {
113
114
  * Plugin-aware markup render. Always returns a `RichText`. Built-in style
114
115
  * tags become spans; registered plugin tags are resolved by their handler,
115
116
  * whose returned `RichText` stands in the output where its pair stood, under
116
- * any style tag that encloses the pair. The recursion is into the inner slice
117
- * of each plugin pair, and every recursion node returns a `RichText`.
117
+ * any style tag that encloses the pair.
118
118
  */
119
119
  export declare function renderMarkup(markup: string, options?: RenderMarkupOptions): RichText;
120
+ /**
121
+ * A string as the text it draws, before any highlighting: read as markup
122
+ * unless `markup` is false, its emoji codes replaced either way, as Rich's
123
+ * `render_str` reads one, its `end` the default line end Rich's leaves it.
124
+ * [LAW:single-enforcer]
125
+ */
126
+ export declare function readStr(source: string, markup: boolean): RichText;
127
+ /**
128
+ * The highlighter a string is drawn with under `settings`: its `highlighter`
129
+ * while `highlight` is not false — Rich's `render_str`, which highlights with
130
+ * `console.highlighter` when `highlight` is true or left to the console.
131
+ * [LAW:single-enforcer]
132
+ */
133
+ export declare function activeHighlighter(settings: Pick<DrawOptions, "highlight" | "highlighter">): DrawOptions["highlighter"];
134
+ /**
135
+ * A string as the text it draws, the way Rich's `render_str` makes one: read
136
+ * by `readStr` under `markup`, then highlighted by `activeHighlighter`.
137
+ * `print` and every renderable that is handed a string both draw it this way,
138
+ * so a console's settings mean the same thing wherever the string lands.
139
+ */
140
+ export declare function renderStr(source: string, settings: Pick<DrawOptions, "markup" | "highlight" | "highlighter">): RichText;