cli-kiss 0.2.2 → 0.2.4
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 +1 -1
- package/dist/index.d.ts +711 -1046
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +1 -0
- package/docs/.vitepress/theme/index.ts +4 -0
- package/docs/.vitepress/theme/style.css +4 -0
- package/docs/guide/01_getting_started.md +4 -4
- package/docs/guide/02_commands.md +72 -41
- package/docs/guide/03_options.md +13 -14
- package/docs/guide/04_positionals.md +6 -8
- package/docs/guide/05_types.md +9 -11
- package/docs/guide/06_run.md +4 -5
- package/docs/index.md +8 -3
- package/docs/public/hero.png +0 -0
- package/package.json +1 -1
- package/src/lib/Command.ts +151 -275
- package/src/lib/Operation.ts +57 -95
- package/src/lib/Option.ts +194 -181
- package/src/lib/Positional.ts +54 -112
- package/src/lib/Reader.ts +155 -156
- package/src/lib/Run.ts +64 -69
- package/src/lib/Type.ts +89 -145
- package/src/lib/Typo.ts +131 -195
- package/src/lib/Usage.ts +203 -69
- package/tests/unit.Reader.aliases.ts +31 -15
- package/tests/unit.Reader.commons.ts +99 -43
- package/tests/unit.Reader.shortBig.ts +75 -31
- package/tests/unit.command.execute.ts +146 -91
- package/tests/unit.command.usage.ts +235 -114
- package/tests/unit.runner.cycle.ts +50 -20
- package/tests/unit.runner.errors.ts +19 -3
package/src/lib/Typo.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Colors are divided into two groups:
|
|
5
|
-
* - **dark** variants correspond to standard ANSI colors (codes 30–37 / 40–47).
|
|
6
|
-
* - **bright** variants correspond to high-intensity ANSI colors (codes 90–97 / 100–107).
|
|
7
|
-
*
|
|
8
|
-
* Used by {@link TypoStyle}'s `fgColor` and `bgColor` fields.
|
|
2
|
+
* Color names for terminal styling, used by {@link TypoStyle}.
|
|
3
|
+
* `dark*` = standard ANSI (30–37); `bright*` = high-intensity (90–97).
|
|
9
4
|
*/
|
|
10
5
|
export type TypoColor =
|
|
11
6
|
| "darkBlack"
|
|
@@ -26,165 +21,168 @@ export type TypoColor =
|
|
|
26
21
|
| "brightWhite";
|
|
27
22
|
|
|
28
23
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* All fields are optional. When `TypoSupport` is in `"none"` mode, no styling is
|
|
33
|
-
* applied and the raw text is returned unchanged. In `"tty"` mode the corresponding
|
|
34
|
-
* ANSI escape codes are emitted. In `"mock"` mode a deterministic textual representation
|
|
35
|
-
* is produced (useful for snapshot tests).
|
|
24
|
+
* Visual styling applied by a {@link TypoSupport} instance.
|
|
25
|
+
* All fields are optional; ignored entirely in `"none"` mode.
|
|
36
26
|
*/
|
|
37
27
|
export type TypoStyle = {
|
|
38
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Foreground (text) color.
|
|
30
|
+
*/
|
|
39
31
|
fgColor?: TypoColor;
|
|
40
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* Background color.
|
|
34
|
+
*/
|
|
41
35
|
bgColor?: TypoColor;
|
|
42
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Reduced intensity.
|
|
38
|
+
*/
|
|
43
39
|
dim?: boolean;
|
|
44
|
-
/**
|
|
40
|
+
/**
|
|
41
|
+
* Bold.
|
|
42
|
+
*/
|
|
45
43
|
bold?: boolean;
|
|
46
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Italic.
|
|
46
|
+
*/
|
|
47
47
|
italic?: boolean;
|
|
48
|
-
/**
|
|
48
|
+
/**
|
|
49
|
+
* Underline.
|
|
50
|
+
*/
|
|
49
51
|
underline?: boolean;
|
|
50
|
-
/**
|
|
52
|
+
/**
|
|
53
|
+
* Strikethrough.
|
|
54
|
+
*/
|
|
51
55
|
strikethrough?: boolean;
|
|
52
56
|
};
|
|
53
57
|
|
|
54
58
|
/**
|
|
55
|
-
*
|
|
56
|
-
* `"Positionals:"`, `"Options:"`).
|
|
57
|
-
* Rendered in bold dark-green.
|
|
59
|
+
* Section title style. Bold dark-green.
|
|
58
60
|
*/
|
|
59
61
|
export const typoStyleTitle: TypoStyle = {
|
|
60
62
|
fgColor: "darkGreen",
|
|
61
63
|
bold: true,
|
|
62
64
|
};
|
|
63
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Logic/type identifier style. Bold dark-magenta.
|
|
67
|
+
*/
|
|
64
68
|
export const typoStyleLogic: TypoStyle = {
|
|
65
69
|
fgColor: "darkMagenta",
|
|
66
70
|
bold: true,
|
|
67
71
|
};
|
|
68
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Quoted user-input style. Bold dark-yellow.
|
|
74
|
+
*/
|
|
69
75
|
export const typoStyleQuote: TypoStyle = {
|
|
70
76
|
fgColor: "darkYellow",
|
|
71
77
|
bold: true,
|
|
72
78
|
};
|
|
73
79
|
|
|
74
|
-
/**
|
|
80
|
+
/**
|
|
81
|
+
* Error label style. Bold dark-red.
|
|
82
|
+
*/
|
|
75
83
|
export const typoStyleFailure: TypoStyle = {
|
|
76
84
|
fgColor: "darkRed",
|
|
77
85
|
bold: true,
|
|
78
86
|
};
|
|
79
87
|
|
|
80
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* Option/command name style. Bold dark-cyan.
|
|
90
|
+
*/
|
|
81
91
|
export const typoStyleConstants: TypoStyle = {
|
|
82
92
|
fgColor: "darkCyan",
|
|
83
93
|
bold: true,
|
|
84
94
|
};
|
|
85
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Positional/user-input label style. Bold dark-blue.
|
|
97
|
+
*/
|
|
86
98
|
export const typoStyleUserInput: TypoStyle = {
|
|
87
99
|
fgColor: "darkBlue",
|
|
88
100
|
bold: true,
|
|
89
101
|
};
|
|
90
102
|
|
|
91
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Strong text style. Bold.
|
|
105
|
+
*/
|
|
92
106
|
export const typoStyleRegularStrong: TypoStyle = {
|
|
93
107
|
bold: true,
|
|
94
108
|
};
|
|
95
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* Subtle text style. Italic and dim.
|
|
111
|
+
*/
|
|
96
112
|
export const typoStyleRegularWeaker: TypoStyle = {
|
|
97
113
|
italic: true,
|
|
98
114
|
dim: true,
|
|
99
115
|
};
|
|
100
116
|
|
|
101
117
|
/**
|
|
102
|
-
*
|
|
103
|
-
* {@link TypoStyle}.
|
|
104
|
-
*
|
|
105
|
-
* Multiple `TypoString`s are composed into a {@link TypoText} for multi-part messages.
|
|
106
|
-
* Rendering is deferred until {@link TypoString.computeStyledString} is called with a
|
|
107
|
-
* {@link TypoSupport} instance.
|
|
118
|
+
* Immutable styled string segment. Compose into a {@link TypoText}.
|
|
108
119
|
*/
|
|
109
120
|
export class TypoString {
|
|
110
121
|
#value: string;
|
|
111
122
|
#typoStyle: TypoStyle;
|
|
112
123
|
/**
|
|
113
|
-
* @param value -
|
|
114
|
-
* @param typoStyle -
|
|
124
|
+
* @param value - Raw text content.
|
|
125
|
+
* @param typoStyle - Style to apply when rendering. Defaults to `{}` (no style).
|
|
115
126
|
*/
|
|
116
127
|
constructor(value: string, typoStyle: TypoStyle = {}) {
|
|
117
128
|
this.#value = value;
|
|
118
129
|
this.#typoStyle = typoStyle;
|
|
119
130
|
}
|
|
120
|
-
/** Returns the unstyled raw text content. */
|
|
121
|
-
getRawString(): string {
|
|
122
|
-
return this.#value;
|
|
123
|
-
}
|
|
124
131
|
/**
|
|
125
|
-
* Returns the text
|
|
132
|
+
* Returns the text styled by `typoSupport`.
|
|
126
133
|
*
|
|
127
|
-
* @param typoSupport -
|
|
134
|
+
* @param typoSupport - Rendering mode.
|
|
128
135
|
*/
|
|
129
136
|
computeStyledString(typoSupport: TypoSupport): string {
|
|
130
137
|
return typoSupport.computeStyledString(this.#value, this.#typoStyle);
|
|
131
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Returns the raw text.
|
|
141
|
+
*/
|
|
142
|
+
getRawString(): string {
|
|
143
|
+
return this.#value;
|
|
144
|
+
}
|
|
132
145
|
}
|
|
133
146
|
|
|
134
147
|
/**
|
|
135
|
-
*
|
|
136
|
-
* multi-part message.
|
|
137
|
-
*
|
|
138
|
-
* `TypoText` is used throughout the library to build error messages and usage output
|
|
139
|
-
* that carry styling information without being coupled to a specific output mode.
|
|
140
|
-
* Rendering is deferred to {@link TypoText.computeStyledString}.
|
|
148
|
+
* Mutable sequence of {@link TypoString} segments.
|
|
141
149
|
*/
|
|
142
150
|
export class TypoText {
|
|
143
151
|
#typoStrings: Array<TypoString>;
|
|
144
152
|
/**
|
|
145
|
-
*
|
|
146
|
-
* `TypoText` (flattened by value), a `TypoString`, or a plain `string` (wrapped in an
|
|
147
|
-
* unstyled `TypoString`).
|
|
148
|
-
*
|
|
149
|
-
* @param typoParts - Initial parts to append. Can be any mix of `TypoText`,
|
|
150
|
-
* `TypoString`, and `string`.
|
|
153
|
+
* @param segments - Initial text segments
|
|
151
154
|
*/
|
|
152
|
-
constructor(
|
|
155
|
+
constructor(
|
|
156
|
+
...segments: Array<TypoText | Array<TypoString> | TypoString | string>
|
|
157
|
+
) {
|
|
153
158
|
this.#typoStrings = [];
|
|
154
|
-
for (const typoPart of
|
|
155
|
-
|
|
156
|
-
this.pushText(typoPart);
|
|
157
|
-
} else if (typoPart instanceof TypoString) {
|
|
158
|
-
this.pushString(typoPart);
|
|
159
|
-
} else if (typeof typoPart === "string") {
|
|
160
|
-
this.pushString(new TypoString(typoPart));
|
|
161
|
-
}
|
|
159
|
+
for (const typoPart of segments) {
|
|
160
|
+
this.push(typoPart);
|
|
162
161
|
}
|
|
163
162
|
}
|
|
164
163
|
/**
|
|
165
|
-
* Appends
|
|
164
|
+
* Appends new text segment(s).
|
|
166
165
|
*
|
|
167
|
-
* @param
|
|
166
|
+
* @param segment - Text segment(s) to append.
|
|
168
167
|
*/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
this.#typoStrings.push(typoString);
|
|
168
|
+
push(segment: TypoText | Array<TypoString> | TypoString | string) {
|
|
169
|
+
if (typeof segment === "string") {
|
|
170
|
+
this.#typoStrings.push(new TypoString(segment));
|
|
171
|
+
} else if (segment instanceof TypoText) {
|
|
172
|
+
this.#typoStrings.push(...segment.#typoStrings);
|
|
173
|
+
} else if (Array.isArray(segment)) {
|
|
174
|
+
for (const typoString of segment) {
|
|
175
|
+
this.#typoStrings.push(typoString);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
this.#typoStrings.push(segment);
|
|
181
179
|
}
|
|
182
180
|
}
|
|
183
181
|
/**
|
|
184
|
-
* Renders all segments into a single string
|
|
182
|
+
* Renders all segments into a single styled string.
|
|
185
183
|
*
|
|
186
|
-
* @param typoSupport -
|
|
187
|
-
* @returns
|
|
184
|
+
* @param typoSupport - Rendering mode.
|
|
185
|
+
* @returns Concatenated styled string.
|
|
188
186
|
*/
|
|
189
187
|
computeStyledString(typoSupport: TypoSupport): string {
|
|
190
188
|
return this.#typoStrings
|
|
@@ -192,16 +190,13 @@ export class TypoText {
|
|
|
192
190
|
.join("");
|
|
193
191
|
}
|
|
194
192
|
/**
|
|
195
|
-
* Returns the
|
|
196
|
-
* Equivalent to calling {@link TypoText.computeStyledString} with
|
|
197
|
-
* {@link TypoSupport.none}.
|
|
193
|
+
* Returns the concatenated raw text.
|
|
198
194
|
*/
|
|
199
195
|
computeRawString(): string {
|
|
200
196
|
return this.#typoStrings.map((t) => t.getRawString()).join("");
|
|
201
197
|
}
|
|
202
198
|
/**
|
|
203
|
-
* Returns the total
|
|
204
|
-
* Used by {@link TypoGrid} to compute column widths for alignment.
|
|
199
|
+
* Returns the total raw character count.
|
|
205
200
|
*/
|
|
206
201
|
computeRawLength(): number {
|
|
207
202
|
let length = 0;
|
|
@@ -213,14 +208,8 @@ export class TypoText {
|
|
|
213
208
|
}
|
|
214
209
|
|
|
215
210
|
/**
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* Each row is an array of `TypoText` cells. When {@link TypoGrid.computeStyledGrid} is
|
|
219
|
-
* called, each column is padded to the width of its widest cell (measured in raw
|
|
220
|
-
* characters). The last column in each row is **not** padded.
|
|
221
|
-
*
|
|
222
|
-
* Used internally by {@link usageToStyledLines} to render the `Positionals:`,
|
|
223
|
-
* `Subcommands:`, and `Options:` sections with neat alignment.
|
|
211
|
+
* Column-aligned grid of {@link TypoText} cells.
|
|
212
|
+
* Each column is padded to the widest cell (raw chars); the last column is not padded.
|
|
224
213
|
*/
|
|
225
214
|
export class TypoGrid {
|
|
226
215
|
#typoRows: Array<Array<TypoText>>;
|
|
@@ -228,25 +217,22 @@ export class TypoGrid {
|
|
|
228
217
|
this.#typoRows = [];
|
|
229
218
|
}
|
|
230
219
|
/**
|
|
231
|
-
* Appends a row
|
|
220
|
+
* Appends a row. All rows should have the same cell count.
|
|
232
221
|
*
|
|
233
|
-
* @param cells -
|
|
234
|
-
* should have the same number of cells for alignment to be meaningful.
|
|
222
|
+
* @param cells - Ordered {@link TypoText} cells.
|
|
235
223
|
*/
|
|
236
224
|
pushRow(cells: Array<TypoText>) {
|
|
237
225
|
this.#typoRows.push(cells);
|
|
238
226
|
}
|
|
239
227
|
/**
|
|
240
|
-
* Renders
|
|
241
|
-
* between columns (except after the last column).
|
|
228
|
+
* Renders as an array of styled, column-padded strings.
|
|
242
229
|
*
|
|
243
|
-
* @param typoSupport -
|
|
244
|
-
* @returns
|
|
245
|
-
* one row. Join the inner arrays with `""` to get a single line string.
|
|
230
|
+
* @param typoSupport - Rendering mode.
|
|
231
|
+
* @returns 2-D array of styled strings.
|
|
246
232
|
*/
|
|
247
|
-
|
|
233
|
+
computeStyledLines(typoSupport: TypoSupport): Array<string> {
|
|
248
234
|
const widths = new Array<number>();
|
|
249
|
-
const
|
|
235
|
+
const styledLines = new Array<string>();
|
|
250
236
|
for (const typoGridRow of this.#typoRows) {
|
|
251
237
|
for (
|
|
252
238
|
let typoGridColumnIndex = 0;
|
|
@@ -264,85 +250,67 @@ export class TypoGrid {
|
|
|
264
250
|
}
|
|
265
251
|
}
|
|
266
252
|
for (const typoGridRow of this.#typoRows) {
|
|
267
|
-
const
|
|
253
|
+
const styledGridRow = new Array<string>();
|
|
268
254
|
for (
|
|
269
255
|
let typoGridColumnIndex = 0;
|
|
270
256
|
typoGridColumnIndex < typoGridRow.length;
|
|
271
257
|
typoGridColumnIndex++
|
|
272
258
|
) {
|
|
273
259
|
const typoGridCell = typoGridRow[typoGridColumnIndex]!;
|
|
274
|
-
|
|
275
|
-
printableGridRow.push(printableGridCell);
|
|
260
|
+
styledGridRow.push(typoGridCell.computeStyledString(typoSupport));
|
|
276
261
|
if (typoGridColumnIndex < typoGridRow.length - 1) {
|
|
277
262
|
const width = typoGridCell.computeRawLength();
|
|
278
263
|
const padding = " ".repeat(widths[typoGridColumnIndex]! - width);
|
|
279
|
-
|
|
264
|
+
styledGridRow.push(padding);
|
|
280
265
|
}
|
|
281
266
|
}
|
|
282
|
-
|
|
267
|
+
styledLines.push(styledGridRow.join(""));
|
|
283
268
|
}
|
|
284
|
-
return
|
|
269
|
+
return styledLines;
|
|
285
270
|
}
|
|
286
271
|
}
|
|
287
272
|
|
|
288
273
|
/**
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
*
|
|
292
|
-
* `TypoError` is used throughout `cli-kiss` to report parsing failures (unknown option,
|
|
293
|
-
* type decoding error, missing required argument, etc.). Its styled representation is
|
|
294
|
-
* rendered by {@link TypoSupport.computeStyledErrorMessage} when outputting errors to
|
|
295
|
-
* the terminal.
|
|
296
|
-
*
|
|
297
|
-
* Errors can be chained: if `source` is a `TypoError`, its styled text is appended
|
|
298
|
-
* after `": "` to form the full message context chain.
|
|
274
|
+
* `Error` subclass with a {@link TypoText} styled message for rich terminal output.
|
|
275
|
+
* Chains `TypoError` sources after `": "`.
|
|
299
276
|
*/
|
|
300
277
|
export class TypoError extends Error {
|
|
301
278
|
#typoText: TypoText;
|
|
302
279
|
/**
|
|
303
|
-
* @param currentTypoText -
|
|
304
|
-
* @param source -
|
|
305
|
-
* appended (chained context). If it is a plain `Error`, its `.message` is appended
|
|
306
|
-
* as a plain string. Any other value is stringified with `String()`.
|
|
280
|
+
* @param currentTypoText - Styled message for this error.
|
|
281
|
+
* @param source - Optional cause; `TypoError` chains styled text, `Error` appends `.message`, else `String()`.
|
|
307
282
|
*/
|
|
308
283
|
constructor(currentTypoText: TypoText, source?: unknown) {
|
|
309
284
|
const typoText = new TypoText();
|
|
310
|
-
typoText.
|
|
285
|
+
typoText.push(currentTypoText);
|
|
311
286
|
if (source instanceof TypoError) {
|
|
312
|
-
typoText.
|
|
313
|
-
typoText.
|
|
287
|
+
typoText.push(new TypoString(": "));
|
|
288
|
+
typoText.push(source.#typoText);
|
|
314
289
|
} else if (source instanceof Error) {
|
|
315
|
-
typoText.
|
|
290
|
+
typoText.push(new TypoString(`: ${source.message}`));
|
|
316
291
|
} else if (source !== undefined) {
|
|
317
|
-
typoText.
|
|
292
|
+
typoText.push(new TypoString(`: ${String(source)}`));
|
|
318
293
|
}
|
|
319
294
|
super(typoText.computeRawString());
|
|
320
295
|
this.#typoText = typoText;
|
|
321
296
|
}
|
|
322
297
|
/**
|
|
323
|
-
* Renders
|
|
298
|
+
* Renders the styled message (without `"Error:"` prefix).
|
|
324
299
|
*
|
|
325
|
-
* @param typoSupport -
|
|
326
|
-
* @returns
|
|
300
|
+
* @param typoSupport - Rendering mode.
|
|
301
|
+
* @returns Styled error string.
|
|
327
302
|
*/
|
|
328
303
|
computeStyledString(typoSupport: TypoSupport): string {
|
|
329
304
|
return this.#typoText.computeStyledString(typoSupport);
|
|
330
305
|
}
|
|
331
306
|
/**
|
|
332
|
-
*
|
|
333
|
-
* is re-thrown as a new `TypoError` whose message is `context()` with the original
|
|
334
|
-
* error chained as the source.
|
|
335
|
-
*
|
|
336
|
-
* This is a convenience helper for adding contextual information to errors that arise
|
|
337
|
-
* deep in a call chain (e.g. "at 0: Number: Unable to parse: ...").
|
|
307
|
+
* Runs `thrower`; wraps any thrown error as a `TypoError` with `context()` prepended.
|
|
338
308
|
*
|
|
339
|
-
* @typeParam Value -
|
|
340
|
-
* @param thrower -
|
|
341
|
-
*
|
|
342
|
-
* @
|
|
343
|
-
*
|
|
344
|
-
* @returns The value returned by `thrower`.
|
|
345
|
-
* @throws `TypoError` wrapping the original error with the provided context prepended.
|
|
309
|
+
* @typeParam Value - Return type of `thrower`.
|
|
310
|
+
* @param thrower - Function to execute; result passed through on success.
|
|
311
|
+
* @param context - Produces the {@link TypoText} prepended to the caught error.
|
|
312
|
+
* @returns Value from `thrower`.
|
|
313
|
+
* @throws `TypoError` wrapping the original error with context prepended.
|
|
346
314
|
*/
|
|
347
315
|
static tryWithContext<Value>(
|
|
348
316
|
thrower: () => Value,
|
|
@@ -357,19 +325,7 @@ export class TypoError extends Error {
|
|
|
357
325
|
}
|
|
358
326
|
|
|
359
327
|
/**
|
|
360
|
-
* Controls
|
|
361
|
-
* {@link TypoString}, {@link TypoText}, and error messages.
|
|
362
|
-
*
|
|
363
|
-
* Instances are created via the static factory methods:
|
|
364
|
-
* - {@link TypoSupport.none} — strips all styling (plain text).
|
|
365
|
-
* - {@link TypoSupport.tty} — applies ANSI escape codes for color terminals.
|
|
366
|
-
* - {@link TypoSupport.mock} — applies a deterministic textual representation useful
|
|
367
|
-
* for snapshot tests.
|
|
368
|
-
* - {@link TypoSupport.inferFromProcess} — auto-detects based on `process.stdout.isTTY`
|
|
369
|
-
* and the `FORCE_COLOR` / `NO_COLOR` environment variables.
|
|
370
|
-
*
|
|
371
|
-
* `TypoSupport` is consumed by {@link runAndExit} (via the `useTtyColors` option)
|
|
372
|
-
* and can also be used directly when building custom usage renderers with {@link usageToStyledLines}.
|
|
328
|
+
* Controls ANSI terminal styling. Create via the static factory methods.
|
|
373
329
|
*/
|
|
374
330
|
export class TypoSupport {
|
|
375
331
|
#kind: "none" | "tty" | "mock";
|
|
@@ -377,39 +333,29 @@ export class TypoSupport {
|
|
|
377
333
|
this.#kind = kind;
|
|
378
334
|
}
|
|
379
335
|
/**
|
|
380
|
-
*
|
|
381
|
-
* as-is (plain text, no ANSI codes).
|
|
336
|
+
* Plain text — no ANSI codes.
|
|
382
337
|
*/
|
|
383
338
|
static none(): TypoSupport {
|
|
384
339
|
return new TypoSupport("none");
|
|
385
340
|
}
|
|
386
341
|
/**
|
|
387
|
-
*
|
|
388
|
-
* Use this when writing to a color-capable terminal (`stdout.isTTY === true`).
|
|
342
|
+
* ANSI escape codes for color terminals.
|
|
389
343
|
*/
|
|
390
344
|
static tty(): TypoSupport {
|
|
391
345
|
return new TypoSupport("tty");
|
|
392
346
|
}
|
|
393
347
|
/**
|
|
394
|
-
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
* `{text}@color`, `{text}+` (bold), `{text}-` (dim), `{text}*` (italic),
|
|
398
|
-
* `{text}_` (underline), `{text}~` (strikethrough). Useful for snapshot testing.
|
|
348
|
+
* Deterministic textual styling for snapshot tests.
|
|
349
|
+
* Style flags appear as suffixes: `{text}@color`, `{text}+` (bold), `{text}-` (dim),
|
|
350
|
+
* `{text}*` (italic), `{text}_` (underline), `{text}~` (strikethrough).
|
|
399
351
|
*/
|
|
400
352
|
static mock(): TypoSupport {
|
|
401
353
|
return new TypoSupport("mock");
|
|
402
354
|
}
|
|
403
355
|
/**
|
|
404
|
-
*
|
|
405
|
-
*
|
|
406
|
-
*
|
|
407
|
-
* 2. `FORCE_COLOR` env var set (any truthy value) → {@link TypoSupport.tty}.
|
|
408
|
-
* 3. `process.stdout.isTTY === true` → {@link TypoSupport.tty}.
|
|
409
|
-
* 4. Otherwise → {@link TypoSupport.none}.
|
|
410
|
-
*
|
|
411
|
-
* Falls back to {@link TypoSupport.none} if `process` is not available (e.g. in a
|
|
412
|
-
* non-Node environment).
|
|
356
|
+
* Auto-detects styling mode from the process environment.
|
|
357
|
+
* `FORCE_COLOR=0` / `NO_COLOR` → none; `FORCE_COLOR` (truthy) / `isTTY` → tty; else → none.
|
|
358
|
+
* Falls back to none if `process` is unavailable.
|
|
413
359
|
*/
|
|
414
360
|
static inferFromProcess(): TypoSupport {
|
|
415
361
|
if (!process) {
|
|
@@ -432,15 +378,11 @@ export class TypoSupport {
|
|
|
432
378
|
return TypoSupport.none();
|
|
433
379
|
}
|
|
434
380
|
/**
|
|
435
|
-
* Applies
|
|
381
|
+
* Applies `typoStyle` to `value` according to the current mode.
|
|
436
382
|
*
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
* @param value - The raw text to style.
|
|
442
|
-
* @param typoStyle - The style to apply.
|
|
443
|
-
* @returns The styled string.
|
|
383
|
+
* @param value - Raw text.
|
|
384
|
+
* @param typoStyle - Style to apply.
|
|
385
|
+
* @returns Styled string.
|
|
444
386
|
*/
|
|
445
387
|
computeStyledString(value: string, typoStyle: TypoStyle): string {
|
|
446
388
|
if (this.#kind === "none") {
|
|
@@ -483,16 +425,10 @@ export class TypoSupport {
|
|
|
483
425
|
throw new Error(`Unknown TypoSupport kind: ${this.#kind}`);
|
|
484
426
|
}
|
|
485
427
|
/**
|
|
486
|
-
* Formats
|
|
487
|
-
*
|
|
488
|
-
* - If `error` is a {@link TypoError}, its styled text is used for the message part.
|
|
489
|
-
* - If `error` is a plain `Error`, its `.message` property is used.
|
|
490
|
-
* - Otherwise `String(error)` is used.
|
|
491
|
-
*
|
|
492
|
-
* The `"Error:"` prefix is always styled with {@link typoStyleFailure}.
|
|
428
|
+
* Formats any thrown value as `"Error: <message>"` with {@link typoStyleFailure} on the prefix.
|
|
493
429
|
*
|
|
494
|
-
* @param error -
|
|
495
|
-
* @returns
|
|
430
|
+
* @param error - Any thrown value.
|
|
431
|
+
* @returns Styled error string.
|
|
496
432
|
*/
|
|
497
433
|
computeStyledErrorMessage(error: unknown): string {
|
|
498
434
|
return [
|