@optique/core 1.3.0-dev.2529 → 1.3.0-dev.2530
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/dist/doc.cjs +93 -84
- package/dist/doc.d.cts +12 -1
- package/dist/doc.d.ts +12 -1
- package/dist/doc.js +88 -79
- package/dist/facade.cjs +49 -15
- package/dist/facade.d.cts +12 -1
- package/dist/facade.d.ts +12 -1
- package/dist/facade.js +48 -14
- package/dist/index.cjs +3 -0
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/internal/terminal.cjs +7 -0
- package/dist/internal/terminal.d.cts +4 -0
- package/dist/internal/terminal.d.ts +4 -0
- package/dist/internal/terminal.js +5 -0
- package/dist/message-registry.cjs +6 -0
- package/dist/message-registry.d.cts +7 -0
- package/dist/message-registry.d.ts +7 -0
- package/dist/message-registry.js +5 -0
- package/dist/message-renderer.cjs +26 -0
- package/dist/message-renderer.d.cts +19 -0
- package/dist/message-renderer.d.ts +19 -0
- package/dist/message-renderer.js +26 -0
- package/dist/message.cjs +49 -85
- package/dist/message.d.cts +31 -1
- package/dist/message.d.ts +31 -1
- package/dist/message.js +49 -86
- package/dist/terminal-internal.cjs +259 -0
- package/dist/terminal-internal.d.cts +36 -0
- package/dist/terminal-internal.d.ts +36 -0
- package/dist/terminal-internal.js +253 -0
- package/dist/terminal.cjs +74 -0
- package/dist/terminal.d.cts +129 -0
- package/dist/terminal.d.ts +129 -0
- package/dist/terminal.js +73 -0
- package/dist/usage.cjs +108 -134
- package/dist/usage.d.cts +6 -0
- package/dist/usage.d.ts +6 -0
- package/dist/usage.js +108 -134
- package/package.json +18 -2
- package/skills/optique/SKILL.md +3 -3
package/dist/message.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { messageRenderers } from "./message-registry.js";
|
|
1
2
|
import { getDisplayWidth } from "./displaywidth.js";
|
|
3
|
+
import { formatTerminalTerm, fragmentTokens, serializeTokens } from "./terminal-internal.js";
|
|
2
4
|
|
|
3
5
|
//#region src/message.ts
|
|
4
6
|
/**
|
|
@@ -294,11 +296,30 @@ function valueSet(values$1, fallbackOrOptions) {
|
|
|
294
296
|
return result;
|
|
295
297
|
}
|
|
296
298
|
function formatMessage(msg, options = {}) {
|
|
299
|
+
return renderMessage(msg, options, {});
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Creates a message formatter using a snapshot of the supplied theme.
|
|
303
|
+
* @param theme Semantic leaf formatters and annotation styles.
|
|
304
|
+
* @returns A reusable message formatter.
|
|
305
|
+
* @throws {TypeError} If initialWidth is not a finite integer.
|
|
306
|
+
* @throws {RangeError} If initialWidth is negative or a color is invalid.
|
|
307
|
+
* @since 1.3.0
|
|
308
|
+
*/
|
|
309
|
+
function createMessageFormatter(theme) {
|
|
310
|
+
const snapshot = { ...theme };
|
|
311
|
+
const formatter = (msg, options = {}) => renderMessage(msg, options, snapshot);
|
|
312
|
+
messageRenderers.set(formatter, (msg, options, ambient) => renderMessage(msg, options, snapshot, ambient));
|
|
313
|
+
return formatter;
|
|
314
|
+
}
|
|
315
|
+
function renderMessage(msg, options, theme, ambient) {
|
|
316
|
+
const initialWidth = options.initialWidth ?? 0;
|
|
317
|
+
if (!Number.isFinite(initialWidth) || !Number.isInteger(initialWidth)) throw new TypeError("Initial width must be a finite integer.");
|
|
318
|
+
if (initialWidth < 0) throw new RangeError("Initial width must be nonnegative.");
|
|
297
319
|
const colorConfig = options.colors ?? false;
|
|
298
320
|
const useColors = typeof colorConfig === "boolean" ? colorConfig : true;
|
|
299
321
|
const resetSuffix = typeof colorConfig === "object" ? colorConfig.resetSuffix ?? "" : "";
|
|
300
322
|
const useQuotes = options.quotes ?? true;
|
|
301
|
-
const resetSequence = `\x1b[0m${resetSuffix}`;
|
|
302
323
|
function* stream() {
|
|
303
324
|
const wordPattern = /\s*\S+\s*/g;
|
|
304
325
|
let prevWasLineBreak = false;
|
|
@@ -314,7 +335,8 @@ function formatMessage(msg, options = {}) {
|
|
|
314
335
|
const breakText = isAfterLineBreak && paragraphIndex === 1 ? "\n" : "\n\n";
|
|
315
336
|
yield {
|
|
316
337
|
text: breakText,
|
|
317
|
-
width: -1
|
|
338
|
+
width: -1,
|
|
339
|
+
scopes: []
|
|
318
340
|
};
|
|
319
341
|
}
|
|
320
342
|
const paragraph = paragraphs[paragraphIndex].replace(/\n/g, " ");
|
|
@@ -324,7 +346,8 @@ function formatMessage(msg, options = {}) {
|
|
|
324
346
|
if (match == null) break;
|
|
325
347
|
yield {
|
|
326
348
|
text: match[0],
|
|
327
|
-
width: getDisplayWidth(match[0])
|
|
349
|
+
width: getDisplayWidth(match[0]),
|
|
350
|
+
scopes: []
|
|
328
351
|
};
|
|
329
352
|
}
|
|
330
353
|
}
|
|
@@ -332,7 +355,8 @@ function formatMessage(msg, options = {}) {
|
|
|
332
355
|
const normalizedText = rawText.replace(/\n/g, " ");
|
|
333
356
|
if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
|
|
334
357
|
text: " ",
|
|
335
|
-
width: 1
|
|
358
|
+
width: 1,
|
|
359
|
+
scopes: []
|
|
336
360
|
};
|
|
337
361
|
else {
|
|
338
362
|
wordPattern.lastIndex = 0;
|
|
@@ -341,105 +365,44 @@ function formatMessage(msg, options = {}) {
|
|
|
341
365
|
if (match == null) break;
|
|
342
366
|
yield {
|
|
343
367
|
text: match[0],
|
|
344
|
-
width: getDisplayWidth(match[0])
|
|
368
|
+
width: getDisplayWidth(match[0]),
|
|
369
|
+
scopes: []
|
|
345
370
|
};
|
|
346
371
|
}
|
|
347
372
|
}
|
|
348
373
|
}
|
|
349
|
-
} else if (term.type === "optionName") {
|
|
350
|
-
const name = useQuotes ? `\`${term.optionName}\`` : term.optionName;
|
|
351
|
-
yield {
|
|
352
|
-
text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
|
|
353
|
-
width: getDisplayWidth(name)
|
|
354
|
-
};
|
|
355
|
-
} else if (term.type === "optionNames") {
|
|
356
|
-
const names = term.optionNames.map((name) => useQuotes ? `\`${name}\`` : name);
|
|
357
|
-
let i = 0;
|
|
358
|
-
for (const name of names) {
|
|
359
|
-
if (i > 0) yield {
|
|
360
|
-
text: "/",
|
|
361
|
-
width: 1
|
|
362
|
-
};
|
|
363
|
-
yield {
|
|
364
|
-
text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
|
|
365
|
-
width: getDisplayWidth(name)
|
|
366
|
-
};
|
|
367
|
-
i++;
|
|
368
|
-
}
|
|
369
|
-
} else if (term.type === "metavar") {
|
|
370
|
-
const metavar$1 = useQuotes ? `\`${term.metavar}\`` : term.metavar;
|
|
371
|
-
yield {
|
|
372
|
-
text: useColors ? `\x1b[1m${metavar$1}${resetSequence}` : metavar$1,
|
|
373
|
-
width: getDisplayWidth(metavar$1)
|
|
374
|
-
};
|
|
375
|
-
} else if (term.type === "value") {
|
|
376
|
-
const value$1 = useQuotes ? `${JSON.stringify(term.value)}` : term.value;
|
|
377
|
-
yield {
|
|
378
|
-
text: useColors ? `\x1b[32m${value$1}${resetSequence}` : value$1,
|
|
379
|
-
width: getDisplayWidth(value$1)
|
|
380
|
-
};
|
|
381
|
-
} else if (term.type === "values") for (let i = 0; i < term.values.length; i++) {
|
|
382
|
-
if (i > 0) yield {
|
|
383
|
-
text: " ",
|
|
384
|
-
width: 1
|
|
385
|
-
};
|
|
386
|
-
const value$1 = useQuotes ? JSON.stringify(term.values[i]) : term.values[i];
|
|
387
|
-
yield {
|
|
388
|
-
text: useColors ? `${i === 0 ? "\x1B[32m" : ""}${value$1}${i + 1 === term.values.length ? resetSequence : ""}` : value$1,
|
|
389
|
-
width: getDisplayWidth(value$1)
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
else if (term.type === "envVar") {
|
|
393
|
-
const envVar$1 = useQuotes ? `\`${term.envVar}\`` : term.envVar;
|
|
394
|
-
yield {
|
|
395
|
-
text: useColors ? `\x1b[1;4m${envVar$1}${resetSequence}` : envVar$1,
|
|
396
|
-
width: getDisplayWidth(envVar$1)
|
|
397
|
-
};
|
|
398
|
-
} else if (term.type === "commandLine") {
|
|
399
|
-
const cmd = useQuotes ? `\`${term.commandLine}\`` : term.commandLine;
|
|
400
|
-
yield {
|
|
401
|
-
text: useColors ? `\x1b[36m${cmd}${resetSequence}` : cmd,
|
|
402
|
-
width: getDisplayWidth(cmd)
|
|
403
|
-
};
|
|
404
374
|
} else if (term.type === "lineBreak") {
|
|
405
375
|
yield {
|
|
406
376
|
text: "\n",
|
|
407
|
-
width: -1
|
|
377
|
+
width: -1,
|
|
378
|
+
scopes: []
|
|
408
379
|
};
|
|
409
380
|
prevWasLineBreak = true;
|
|
410
|
-
} else
|
|
411
|
-
const urlString = term.url.href;
|
|
412
|
-
const displayText = useQuotes ? `<${urlString}>` : urlString;
|
|
413
|
-
if (useColors) {
|
|
414
|
-
const hyperlink = `\x1b]8;;${urlString}\x1b\\${displayText}\x1b]8;;\x1b\\${resetSuffix}`;
|
|
415
|
-
yield {
|
|
416
|
-
text: hyperlink,
|
|
417
|
-
width: getDisplayWidth(displayText)
|
|
418
|
-
};
|
|
419
|
-
} else yield {
|
|
420
|
-
text: displayText,
|
|
421
|
-
width: getDisplayWidth(displayText)
|
|
422
|
-
};
|
|
423
|
-
} else throw new TypeError(`Invalid MessageTerm type: ${term["type"]}.`);
|
|
381
|
+
} else yield* fragmentTokens(formatTerminalTerm(term, theme, useQuotes));
|
|
424
382
|
}
|
|
425
383
|
}
|
|
426
|
-
|
|
427
|
-
let totalWidth =
|
|
428
|
-
for (const
|
|
429
|
-
if (width === -1) {
|
|
430
|
-
|
|
384
|
+
const tokens = [];
|
|
385
|
+
let totalWidth = initialWidth;
|
|
386
|
+
for (const token of stream()) {
|
|
387
|
+
if (token.width === -1) {
|
|
388
|
+
tokens.push(token);
|
|
431
389
|
totalWidth = 0;
|
|
432
390
|
continue;
|
|
433
391
|
}
|
|
434
|
-
if (options.maxWidth != null && totalWidth > 0 && totalWidth + width > options.maxWidth) {
|
|
435
|
-
|
|
392
|
+
if (options.maxWidth != null && totalWidth > 0 && totalWidth + token.width > options.maxWidth) {
|
|
393
|
+
tokens.push({
|
|
394
|
+
text: "\n",
|
|
395
|
+
width: -1,
|
|
396
|
+
scopes: []
|
|
397
|
+
});
|
|
436
398
|
totalWidth = 0;
|
|
437
399
|
}
|
|
438
|
-
|
|
439
|
-
totalWidth += width;
|
|
400
|
+
tokens.push(token);
|
|
401
|
+
totalWidth += token.width;
|
|
440
402
|
}
|
|
441
|
-
return
|
|
403
|
+
return serializeTokens(tokens, useColors, ambient == null ? resetSuffix : "", ambient);
|
|
442
404
|
}
|
|
405
|
+
messageRenderers.set(formatMessage, (msg, options, ambient) => renderMessage(msg, options, {}, ambient));
|
|
443
406
|
|
|
444
407
|
//#endregion
|
|
445
|
-
export { cloneMessage, cloneMessageTerm, commandLine, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, url, value, valueSet, values };
|
|
408
|
+
export { cloneMessage, cloneMessageTerm, commandLine, createMessageFormatter, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, url, value, valueSet, values };
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
const require_displaywidth = require('./displaywidth.cjs');
|
|
2
|
+
const require_terminal = require('./terminal.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/terminal-internal.ts
|
|
5
|
+
function terminalText(text) {
|
|
6
|
+
return {
|
|
7
|
+
type: "text",
|
|
8
|
+
text
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function formatTerminalTerm(term, theme = {}, quotes = false, usage) {
|
|
12
|
+
const quote = (s) => quotes ? `\`${s}\`` : s;
|
|
13
|
+
let text;
|
|
14
|
+
switch (term.type) {
|
|
15
|
+
case "text": return terminalText(term.text);
|
|
16
|
+
case "lineBreak": throw new TypeError("Hard breaks must be rendered at the message level.");
|
|
17
|
+
case "optionName":
|
|
18
|
+
text = quote(term.optionName);
|
|
19
|
+
break;
|
|
20
|
+
case "optionNames":
|
|
21
|
+
text = term.optionNames.map(quote).join("/");
|
|
22
|
+
break;
|
|
23
|
+
case "metavar":
|
|
24
|
+
text = quote(term.metavar);
|
|
25
|
+
break;
|
|
26
|
+
case "value":
|
|
27
|
+
text = quotes ? JSON.stringify(term.value) : term.value;
|
|
28
|
+
break;
|
|
29
|
+
case "values":
|
|
30
|
+
text = term.values.map((v) => quotes ? JSON.stringify(v) : v).join(" ");
|
|
31
|
+
break;
|
|
32
|
+
case "envVar":
|
|
33
|
+
text = quote(term.envVar);
|
|
34
|
+
break;
|
|
35
|
+
case "commandLine":
|
|
36
|
+
text = quote(term.commandLine);
|
|
37
|
+
break;
|
|
38
|
+
case "url":
|
|
39
|
+
text = quotes ? `<${term.url.href}>` : term.url.href;
|
|
40
|
+
break;
|
|
41
|
+
case "programName":
|
|
42
|
+
text = term.programName;
|
|
43
|
+
break;
|
|
44
|
+
case "label":
|
|
45
|
+
case "errorLabel":
|
|
46
|
+
text = term.label;
|
|
47
|
+
break;
|
|
48
|
+
case "syntaxPunctuation":
|
|
49
|
+
text = term.punctuation;
|
|
50
|
+
break;
|
|
51
|
+
default: throw new TypeError(`Invalid MessageTerm type: ${term["type"]}.`);
|
|
52
|
+
}
|
|
53
|
+
const ctx = {
|
|
54
|
+
quotes,
|
|
55
|
+
text,
|
|
56
|
+
usage,
|
|
57
|
+
format: (child) => formatTerminalTerm(child, theme, quotes, usage)
|
|
58
|
+
};
|
|
59
|
+
switch (term.type) {
|
|
60
|
+
case "optionName": return (theme.optionName ?? require_terminal.defaultTerminalTheme.optionName)(term, ctx);
|
|
61
|
+
case "optionNames": return (theme.optionNames ?? require_terminal.defaultTerminalTheme.optionNames)(term, ctx);
|
|
62
|
+
case "metavar": return (theme.metavar ?? require_terminal.defaultTerminalTheme.metavar)(term, ctx);
|
|
63
|
+
case "value": return (theme.value ?? require_terminal.defaultTerminalTheme.value)(term, ctx);
|
|
64
|
+
case "values": return (theme.values ?? require_terminal.defaultTerminalTheme.values)(term, ctx);
|
|
65
|
+
case "envVar": return (theme.envVar ?? require_terminal.defaultTerminalTheme.envVar)(term, ctx);
|
|
66
|
+
case "commandLine": return (theme.commandLine ?? require_terminal.defaultTerminalTheme.commandLine)(term, ctx);
|
|
67
|
+
case "url": return (theme.url ?? require_terminal.defaultTerminalTheme.url)(term, ctx);
|
|
68
|
+
case "programName": return (theme.programName ?? require_terminal.defaultTerminalTheme.programName)(term, ctx);
|
|
69
|
+
case "label": return (theme.label ?? require_terminal.defaultTerminalTheme.label)(term, ctx);
|
|
70
|
+
case "syntaxPunctuation": return (theme.syntaxPunctuation ?? require_terminal.defaultTerminalTheme.syntaxPunctuation)(term, ctx);
|
|
71
|
+
case "errorLabel": return (theme.errorLabel ?? require_terminal.defaultTerminalTheme.errorLabel)(term, ctx);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const colorNames = [
|
|
75
|
+
"black",
|
|
76
|
+
"red",
|
|
77
|
+
"green",
|
|
78
|
+
"yellow",
|
|
79
|
+
"blue",
|
|
80
|
+
"magenta",
|
|
81
|
+
"cyan",
|
|
82
|
+
"white",
|
|
83
|
+
"brightBlack",
|
|
84
|
+
"brightRed",
|
|
85
|
+
"brightGreen",
|
|
86
|
+
"brightYellow",
|
|
87
|
+
"brightBlue",
|
|
88
|
+
"brightMagenta",
|
|
89
|
+
"brightCyan",
|
|
90
|
+
"brightWhite"
|
|
91
|
+
];
|
|
92
|
+
function colorCode(color, background) {
|
|
93
|
+
const channel = (n) => {
|
|
94
|
+
if (!Number.isInteger(n) || n < 0 || n > 255) throw new RangeError("Terminal color channels must be integers from 0 to 255.");
|
|
95
|
+
return n;
|
|
96
|
+
};
|
|
97
|
+
if (typeof color === "string") {
|
|
98
|
+
const i = colorNames.indexOf(color);
|
|
99
|
+
if (i < 0) throw new RangeError("Unknown terminal color.");
|
|
100
|
+
return String((background ? 40 : 30) + (i >= 8 ? 60 + i - 8 : i));
|
|
101
|
+
}
|
|
102
|
+
const prefix = background ? 48 : 38;
|
|
103
|
+
if ("index" in color) return `${prefix};5;${channel(color.index)}`;
|
|
104
|
+
return `${prefix};2;${color.map(channel).join(";")}`;
|
|
105
|
+
}
|
|
106
|
+
function styleCode(style) {
|
|
107
|
+
const codes = [];
|
|
108
|
+
if (style.bold) codes.push(1);
|
|
109
|
+
if (style.dim) codes.push(2);
|
|
110
|
+
if (style.italic) codes.push(3);
|
|
111
|
+
if (style.underline) codes.push(4);
|
|
112
|
+
if (style.foreground != null) codes.push(colorCode(style.foreground, false));
|
|
113
|
+
if (style.background != null) codes.push(colorCode(style.background, true));
|
|
114
|
+
return codes.length ? `\x1b[${codes.join(";")}m` : "";
|
|
115
|
+
}
|
|
116
|
+
function sameStyle(a, b) {
|
|
117
|
+
return a.bold === b.bold && a.dim === b.dim && a.italic === b.italic && a.underline === b.underline && JSON.stringify(a.foreground) === JSON.stringify(b.foreground) && JSON.stringify(a.background) === JSON.stringify(b.background);
|
|
118
|
+
}
|
|
119
|
+
function* fragmentTokens(fragment, scopes = [], inherited = {}) {
|
|
120
|
+
if (fragment.type === "text") {
|
|
121
|
+
yield {
|
|
122
|
+
text: fragment.text,
|
|
123
|
+
width: require_displaywidth.getDisplayWidth(fragment.text),
|
|
124
|
+
scopes
|
|
125
|
+
};
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
let next = scopes;
|
|
129
|
+
let style = inherited;
|
|
130
|
+
if (fragment.type === "style") {
|
|
131
|
+
styleCode(fragment.style);
|
|
132
|
+
style = {
|
|
133
|
+
...inherited,
|
|
134
|
+
...fragment.style
|
|
135
|
+
};
|
|
136
|
+
if (!sameStyle(style, inherited)) next = [...scopes, {
|
|
137
|
+
kind: "style",
|
|
138
|
+
style: fragment.style
|
|
139
|
+
}];
|
|
140
|
+
} else if (fragment.type === "link") next = [...scopes, {
|
|
141
|
+
kind: "link",
|
|
142
|
+
href: fragment.href
|
|
143
|
+
}];
|
|
144
|
+
for (const child of fragment.children) yield* fragmentTokens(child, next, style);
|
|
145
|
+
}
|
|
146
|
+
function serializeTokens(tokens, colors = false, resetSuffix = "", ambient = {}) {
|
|
147
|
+
let output = "";
|
|
148
|
+
let active = [];
|
|
149
|
+
function transition(next) {
|
|
150
|
+
let common = 0;
|
|
151
|
+
while (common < active.length && common < next.length && active[common] === next[common]) common++;
|
|
152
|
+
const surviving = active.slice(0, common);
|
|
153
|
+
const restored = surviving.reduce((style, scope) => ({
|
|
154
|
+
...style,
|
|
155
|
+
...scope.style
|
|
156
|
+
}), ambient);
|
|
157
|
+
let reset = false;
|
|
158
|
+
let closedLink = false;
|
|
159
|
+
for (let i = active.length - 1; i >= common; i--) if (active[i].kind === "link") {
|
|
160
|
+
output += `\x1b]8;;\x1b\\${resetSuffix}${styleCode(restored)}`;
|
|
161
|
+
closedLink = true;
|
|
162
|
+
} else reset = true;
|
|
163
|
+
active = surviving;
|
|
164
|
+
if (closedLink) {
|
|
165
|
+
const parentLink = active.findLast((scope) => scope.kind === "link");
|
|
166
|
+
if (parentLink != null) output += `\x1b]8;;${parentLink.href}\x1b\\`;
|
|
167
|
+
}
|
|
168
|
+
if (reset) output += "\x1B[0m" + resetSuffix + styleCode(restored);
|
|
169
|
+
for (const scope of next.slice(common)) {
|
|
170
|
+
if (scope.kind === "link") output += `\x1b]8;;${scope.href}\x1b\\`;
|
|
171
|
+
else if (scope.style) if (Object.values(scope.style).includes(false)) {
|
|
172
|
+
const inherited = active.reduce((s, x) => ({
|
|
173
|
+
...s,
|
|
174
|
+
...x.style
|
|
175
|
+
}), ambient);
|
|
176
|
+
output += "\x1B[0m" + resetSuffix + styleCode({
|
|
177
|
+
...inherited,
|
|
178
|
+
...scope.style
|
|
179
|
+
});
|
|
180
|
+
} else output += styleCode(scope.style);
|
|
181
|
+
active = [...active, scope];
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const items = [...tokens];
|
|
185
|
+
for (let i = 0; i < items.length; i++) {
|
|
186
|
+
const token = items[i];
|
|
187
|
+
if (colors && token.width === -1) {
|
|
188
|
+
const next = items.slice(i + 1).find((t) => t.width !== -1)?.scopes ?? [];
|
|
189
|
+
let common = 0;
|
|
190
|
+
while (common < active.length && common < next.length && active[common] === next[common]) common++;
|
|
191
|
+
transition(active.slice(0, common));
|
|
192
|
+
} else if (colors) transition(token.scopes);
|
|
193
|
+
output += token.text;
|
|
194
|
+
}
|
|
195
|
+
if (colors) transition([]);
|
|
196
|
+
return output;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Serializes one semantic leaf for a terminal surface outside a message.
|
|
200
|
+
* @param term The semantic leaf to render.
|
|
201
|
+
* @param theme Optional overrides for the default terminal theme.
|
|
202
|
+
* @param colors Whether to emit styles and hyperlinks.
|
|
203
|
+
* @param usage The leaf's usage context, when applicable.
|
|
204
|
+
* @param ambient The style surrounding the rendered leaf.
|
|
205
|
+
* @returns The leaf's styled or plain representation.
|
|
206
|
+
* @throws {TypeError} If the term is a hard break or has an unknown type.
|
|
207
|
+
* @throws {RangeError} If a color channel or palette index is invalid.
|
|
208
|
+
* @since 1.3.0
|
|
209
|
+
* @internal
|
|
210
|
+
*/
|
|
211
|
+
function renderTerminalTerm(term, theme, colors, usage, ambient) {
|
|
212
|
+
return serializeTokens(fragmentTokens(formatTerminalTerm(term, theme, false, usage)), colors, "", ambient);
|
|
213
|
+
}
|
|
214
|
+
/** Memoizes semantic leaves for one layout pass, including measurement. */
|
|
215
|
+
function cacheTerminalTheme(theme = {}) {
|
|
216
|
+
function cache(formatter) {
|
|
217
|
+
const fragments = /* @__PURE__ */ new Map();
|
|
218
|
+
return (term, context) => {
|
|
219
|
+
const key = JSON.stringify([
|
|
220
|
+
term,
|
|
221
|
+
context.quotes,
|
|
222
|
+
context.usage
|
|
223
|
+
]);
|
|
224
|
+
let fragment = fragments.get(key);
|
|
225
|
+
if (fragment == null) {
|
|
226
|
+
fragment = formatter(term, context);
|
|
227
|
+
fragments.set(key, fragment);
|
|
228
|
+
}
|
|
229
|
+
return fragment;
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
return {
|
|
233
|
+
optionName: cache(theme.optionName ?? require_terminal.defaultTerminalTheme.optionName),
|
|
234
|
+
optionNames: cache(theme.optionNames ?? require_terminal.defaultTerminalTheme.optionNames),
|
|
235
|
+
metavar: cache(theme.metavar ?? require_terminal.defaultTerminalTheme.metavar),
|
|
236
|
+
value: cache(theme.value ?? require_terminal.defaultTerminalTheme.value),
|
|
237
|
+
values: cache(theme.values ?? require_terminal.defaultTerminalTheme.values),
|
|
238
|
+
envVar: cache(theme.envVar ?? require_terminal.defaultTerminalTheme.envVar),
|
|
239
|
+
commandLine: cache(theme.commandLine ?? require_terminal.defaultTerminalTheme.commandLine),
|
|
240
|
+
url: cache(theme.url ?? require_terminal.defaultTerminalTheme.url),
|
|
241
|
+
programName: cache(theme.programName ?? require_terminal.defaultTerminalTheme.programName),
|
|
242
|
+
label: cache(theme.label ?? require_terminal.defaultTerminalTheme.label),
|
|
243
|
+
syntaxPunctuation: cache(theme.syntaxPunctuation ?? require_terminal.defaultTerminalTheme.syntaxPunctuation),
|
|
244
|
+
errorLabel: cache(theme.errorLabel ?? require_terminal.defaultTerminalTheme.errorLabel),
|
|
245
|
+
annotationStyles: theme.annotationStyles == null ? void 0 : {
|
|
246
|
+
default: theme.annotationStyles.default == null ? void 0 : { ...theme.annotationStyles.default },
|
|
247
|
+
choices: theme.annotationStyles.choices == null ? void 0 : { ...theme.annotationStyles.choices }
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
//#endregion
|
|
253
|
+
exports.cacheTerminalTheme = cacheTerminalTheme;
|
|
254
|
+
exports.formatTerminalTerm = formatTerminalTerm;
|
|
255
|
+
exports.fragmentTokens = fragmentTokens;
|
|
256
|
+
exports.renderTerminalTerm = renderTerminalTerm;
|
|
257
|
+
exports.serializeTokens = serializeTokens;
|
|
258
|
+
exports.styleCode = styleCode;
|
|
259
|
+
exports.terminalText = terminalText;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TerminalFormatContext, TerminalFragment, TerminalStyle, TerminalTerm, TerminalTheme } from "./terminal.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/terminal-internal.d.ts
|
|
4
|
+
interface Scope {
|
|
5
|
+
readonly kind: "style" | "link";
|
|
6
|
+
readonly style?: TerminalStyle;
|
|
7
|
+
readonly href?: string;
|
|
8
|
+
}
|
|
9
|
+
interface TerminalToken {
|
|
10
|
+
readonly text: string;
|
|
11
|
+
readonly width: number;
|
|
12
|
+
readonly scopes: readonly Scope[];
|
|
13
|
+
}
|
|
14
|
+
declare function terminalText(text: string): TerminalFragment;
|
|
15
|
+
declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
|
|
16
|
+
declare function styleCode(style: TerminalStyle): string;
|
|
17
|
+
declare function fragmentTokens(fragment: TerminalFragment, scopes?: readonly Scope[], inherited?: TerminalStyle): Generator<TerminalToken>;
|
|
18
|
+
declare function serializeTokens(tokens: Iterable<TerminalToken>, colors?: boolean, resetSuffix?: string, ambient?: TerminalStyle): string;
|
|
19
|
+
/**
|
|
20
|
+
* Serializes one semantic leaf for a terminal surface outside a message.
|
|
21
|
+
* @param term The semantic leaf to render.
|
|
22
|
+
* @param theme Optional overrides for the default terminal theme.
|
|
23
|
+
* @param colors Whether to emit styles and hyperlinks.
|
|
24
|
+
* @param usage The leaf's usage context, when applicable.
|
|
25
|
+
* @param ambient The style surrounding the rendered leaf.
|
|
26
|
+
* @returns The leaf's styled or plain representation.
|
|
27
|
+
* @throws {TypeError} If the term is a hard break or has an unknown type.
|
|
28
|
+
* @throws {RangeError} If a color channel or palette index is invalid.
|
|
29
|
+
* @since 1.3.0
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
declare function renderTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, colors?: boolean, usage?: TerminalFormatContext["usage"], ambient?: TerminalStyle): string;
|
|
33
|
+
/** Memoizes semantic leaves for one layout pass, including measurement. */
|
|
34
|
+
declare function cacheTerminalTheme(theme?: TerminalTheme): TerminalTheme;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { Scope, TerminalToken, cacheTerminalTheme, formatTerminalTerm, fragmentTokens, renderTerminalTerm, serializeTokens, styleCode, terminalText };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TerminalFormatContext, TerminalFragment, TerminalStyle, TerminalTerm, TerminalTheme } from "./terminal.js";
|
|
2
|
+
|
|
3
|
+
//#region src/terminal-internal.d.ts
|
|
4
|
+
interface Scope {
|
|
5
|
+
readonly kind: "style" | "link";
|
|
6
|
+
readonly style?: TerminalStyle;
|
|
7
|
+
readonly href?: string;
|
|
8
|
+
}
|
|
9
|
+
interface TerminalToken {
|
|
10
|
+
readonly text: string;
|
|
11
|
+
readonly width: number;
|
|
12
|
+
readonly scopes: readonly Scope[];
|
|
13
|
+
}
|
|
14
|
+
declare function terminalText(text: string): TerminalFragment;
|
|
15
|
+
declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
|
|
16
|
+
declare function styleCode(style: TerminalStyle): string;
|
|
17
|
+
declare function fragmentTokens(fragment: TerminalFragment, scopes?: readonly Scope[], inherited?: TerminalStyle): Generator<TerminalToken>;
|
|
18
|
+
declare function serializeTokens(tokens: Iterable<TerminalToken>, colors?: boolean, resetSuffix?: string, ambient?: TerminalStyle): string;
|
|
19
|
+
/**
|
|
20
|
+
* Serializes one semantic leaf for a terminal surface outside a message.
|
|
21
|
+
* @param term The semantic leaf to render.
|
|
22
|
+
* @param theme Optional overrides for the default terminal theme.
|
|
23
|
+
* @param colors Whether to emit styles and hyperlinks.
|
|
24
|
+
* @param usage The leaf's usage context, when applicable.
|
|
25
|
+
* @param ambient The style surrounding the rendered leaf.
|
|
26
|
+
* @returns The leaf's styled or plain representation.
|
|
27
|
+
* @throws {TypeError} If the term is a hard break or has an unknown type.
|
|
28
|
+
* @throws {RangeError} If a color channel or palette index is invalid.
|
|
29
|
+
* @since 1.3.0
|
|
30
|
+
* @internal
|
|
31
|
+
*/
|
|
32
|
+
declare function renderTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, colors?: boolean, usage?: TerminalFormatContext["usage"], ambient?: TerminalStyle): string;
|
|
33
|
+
/** Memoizes semantic leaves for one layout pass, including measurement. */
|
|
34
|
+
declare function cacheTerminalTheme(theme?: TerminalTheme): TerminalTheme;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { Scope, TerminalToken, cacheTerminalTheme, formatTerminalTerm, fragmentTokens, renderTerminalTerm, serializeTokens, styleCode, terminalText };
|