@optique/core 1.3.2 → 1.3.3
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 +11 -3
- package/dist/doc.js +12 -4
- package/dist/message.cjs +32 -5
- package/dist/message.js +33 -6
- package/dist/terminal-internal.cjs +4 -1
- package/dist/terminal-internal.d.cts +5 -0
- package/dist/terminal-internal.d.ts +5 -0
- package/dist/terminal-internal.js +4 -1
- package/dist/terminal-separators.cjs +13 -0
- package/dist/terminal-separators.js +12 -0
- package/dist/terminal.cjs +4 -1
- package/dist/terminal.js +5 -1
- package/dist/text-layout.cjs +14 -1
- package/dist/text-layout.d.cts +8 -1
- package/dist/text-layout.d.ts +8 -1
- package/dist/text-layout.js +13 -1
- package/package.json +2 -2
package/dist/doc.cjs
CHANGED
|
@@ -431,8 +431,16 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
431
431
|
column: extraTermOffset
|
|
432
432
|
}).cursor;
|
|
433
433
|
const appendAnnotation = (content, layout, style, ambient, quotes) => {
|
|
434
|
-
|
|
435
|
-
|
|
434
|
+
let prefixText = layout.prefix;
|
|
435
|
+
let prefix = require_text_layout.placeText(prefixText, cursor, descColumnWidth, 1);
|
|
436
|
+
if (prefix.text !== layout.prefix) {
|
|
437
|
+
description += "\n";
|
|
438
|
+
prefixText = require_text_layout.trimLeadingSpace(layout.prefix);
|
|
439
|
+
prefix = require_text_layout.placeText(prefixText, {
|
|
440
|
+
line: "",
|
|
441
|
+
column: 0
|
|
442
|
+
});
|
|
443
|
+
}
|
|
436
444
|
const rendered = formatMessage(content, {
|
|
437
445
|
colors: options.colors ? { resetSuffix: style } : false,
|
|
438
446
|
quotes,
|
|
@@ -440,7 +448,7 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
440
448
|
initialWidth: descColumnWidth != null || layout.prefixMetrics.lineCount > 1 ? prefix.cursor.column : void 0
|
|
441
449
|
}, ambient);
|
|
442
450
|
const suffix = require_text_layout.placeText(layout.suffix, require_text_layout.placeText(rendered, prefix.cursor).cursor, descColumnWidth);
|
|
443
|
-
const annotationText = `${
|
|
451
|
+
const annotationText = `${prefixText}${rendered}${opaqueFormatter && options.colors ? style : ""}${suffix.text}`;
|
|
444
452
|
description += options.colors ? `${style}${annotationText}${style ? "\x1B[0m" : ""}` : annotationText;
|
|
445
453
|
cursor = suffix.cursor;
|
|
446
454
|
};
|
package/dist/doc.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { cacheTerminalTheme, renderTerminalTerm, styleCode } from "./terminal-internal.js";
|
|
2
|
-
import { measureAnnotation, measureText, placeText, spaceAfterLabel } from "./text-layout.js";
|
|
2
|
+
import { measureAnnotation, measureText, placeText, spaceAfterLabel, trimLeadingSpace } from "./text-layout.js";
|
|
3
3
|
import { validateLabel, validateProgramName } from "./validate.js";
|
|
4
4
|
import { cloneUsageTerm, formatUsage, formatUsageTerm, isDocHidden } from "./usage.js";
|
|
5
5
|
import { hasAutomaticWidth, minimumUsageWidth, reportAutomaticWidth } from "./terminal-width.js";
|
|
@@ -431,8 +431,16 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
431
431
|
column: extraTermOffset
|
|
432
432
|
}).cursor;
|
|
433
433
|
const appendAnnotation = (content, layout, style, ambient, quotes) => {
|
|
434
|
-
|
|
435
|
-
|
|
434
|
+
let prefixText = layout.prefix;
|
|
435
|
+
let prefix = placeText(prefixText, cursor, descColumnWidth, 1);
|
|
436
|
+
if (prefix.text !== layout.prefix) {
|
|
437
|
+
description += "\n";
|
|
438
|
+
prefixText = trimLeadingSpace(layout.prefix);
|
|
439
|
+
prefix = placeText(prefixText, {
|
|
440
|
+
line: "",
|
|
441
|
+
column: 0
|
|
442
|
+
});
|
|
443
|
+
}
|
|
436
444
|
const rendered = formatMessage(content, {
|
|
437
445
|
colors: options.colors ? { resetSuffix: style } : false,
|
|
438
446
|
quotes,
|
|
@@ -440,7 +448,7 @@ function formatDocPage(programName, page, options = {}) {
|
|
|
440
448
|
initialWidth: descColumnWidth != null || layout.prefixMetrics.lineCount > 1 ? prefix.cursor.column : void 0
|
|
441
449
|
}, ambient);
|
|
442
450
|
const suffix = placeText(layout.suffix, placeText(rendered, prefix.cursor).cursor, descColumnWidth);
|
|
443
|
-
const annotationText = `${
|
|
451
|
+
const annotationText = `${prefixText}${rendered}${opaqueFormatter && options.colors ? style : ""}${suffix.text}`;
|
|
444
452
|
description += options.colors ? `${style}${annotationText}${style ? "\x1B[0m" : ""}` : annotationText;
|
|
445
453
|
cursor = suffix.cursor;
|
|
446
454
|
};
|
package/dist/message.cjs
CHANGED
|
@@ -347,7 +347,8 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
347
347
|
yield {
|
|
348
348
|
text: match[0],
|
|
349
349
|
width: require_displaywidth.getDisplayWidth(match[0]),
|
|
350
|
-
scopes: []
|
|
350
|
+
scopes: [],
|
|
351
|
+
trimOnWrap: true
|
|
351
352
|
};
|
|
352
353
|
}
|
|
353
354
|
}
|
|
@@ -356,7 +357,8 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
356
357
|
if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
|
|
357
358
|
text: " ",
|
|
358
359
|
width: 1,
|
|
359
|
-
scopes: []
|
|
360
|
+
scopes: [],
|
|
361
|
+
trimOnWrap: true
|
|
360
362
|
};
|
|
361
363
|
else {
|
|
362
364
|
wordPattern.lastIndex = 0;
|
|
@@ -366,7 +368,8 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
366
368
|
yield {
|
|
367
369
|
text: match[0],
|
|
368
370
|
width: require_displaywidth.getDisplayWidth(match[0]),
|
|
369
|
-
scopes: []
|
|
371
|
+
scopes: [],
|
|
372
|
+
trimOnWrap: true
|
|
370
373
|
};
|
|
371
374
|
}
|
|
372
375
|
}
|
|
@@ -383,22 +386,46 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
383
386
|
}
|
|
384
387
|
const tokens = [];
|
|
385
388
|
let totalWidth = initialWidth;
|
|
386
|
-
|
|
389
|
+
let pendingWrap = false;
|
|
390
|
+
let atWrappedLineStart = false;
|
|
391
|
+
for (let token of stream()) {
|
|
387
392
|
if (token.width === -1) {
|
|
388
393
|
tokens.push(token);
|
|
389
394
|
totalWidth = 0;
|
|
395
|
+
pendingWrap = false;
|
|
396
|
+
atWrappedLineStart = false;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
const wraps = pendingWrap || options.maxWidth != null && totalWidth > 0 && totalWidth + token.width > options.maxWidth;
|
|
400
|
+
if ((wraps || atWrappedLineStart) && token.trimOnWrap) {
|
|
401
|
+
const text$1 = token.text.trimStart();
|
|
402
|
+
token = {
|
|
403
|
+
...token,
|
|
404
|
+
text: text$1,
|
|
405
|
+
width: token.width - require_displaywidth.getDisplayWidth(token.text.slice(0, token.text.length - text$1.length))
|
|
406
|
+
};
|
|
407
|
+
if (text$1 === "") {
|
|
408
|
+
if (wraps) pendingWrap = true;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (pendingWrap && require_displaywidth.stripAnsi(token.text) === "") {
|
|
413
|
+
tokens.push(token);
|
|
390
414
|
continue;
|
|
391
415
|
}
|
|
392
|
-
if (
|
|
416
|
+
if (wraps) {
|
|
393
417
|
tokens.push({
|
|
394
418
|
text: "\n",
|
|
395
419
|
width: -1,
|
|
396
420
|
scopes: []
|
|
397
421
|
});
|
|
398
422
|
totalWidth = 0;
|
|
423
|
+
pendingWrap = false;
|
|
424
|
+
atWrappedLineStart = true;
|
|
399
425
|
}
|
|
400
426
|
tokens.push(token);
|
|
401
427
|
totalWidth += token.width;
|
|
428
|
+
if (token.width > 0) atWrappedLineStart = false;
|
|
402
429
|
}
|
|
403
430
|
return require_terminal_internal.serializeTokens(tokens, useColors, ambient == null ? resetSuffix : "", ambient);
|
|
404
431
|
}
|
package/dist/message.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getDisplayWidth } from "./displaywidth.js";
|
|
1
|
+
import { getDisplayWidth, stripAnsi } from "./displaywidth.js";
|
|
2
2
|
import { formatTerminalTerm, fragmentTokens, serializeTokens } from "./terminal-internal.js";
|
|
3
3
|
import { messageRenderers } from "./message-registry.js";
|
|
4
4
|
|
|
@@ -347,7 +347,8 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
347
347
|
yield {
|
|
348
348
|
text: match[0],
|
|
349
349
|
width: getDisplayWidth(match[0]),
|
|
350
|
-
scopes: []
|
|
350
|
+
scopes: [],
|
|
351
|
+
trimOnWrap: true
|
|
351
352
|
};
|
|
352
353
|
}
|
|
353
354
|
}
|
|
@@ -356,7 +357,8 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
356
357
|
if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
|
|
357
358
|
text: " ",
|
|
358
359
|
width: 1,
|
|
359
|
-
scopes: []
|
|
360
|
+
scopes: [],
|
|
361
|
+
trimOnWrap: true
|
|
360
362
|
};
|
|
361
363
|
else {
|
|
362
364
|
wordPattern.lastIndex = 0;
|
|
@@ -366,7 +368,8 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
366
368
|
yield {
|
|
367
369
|
text: match[0],
|
|
368
370
|
width: getDisplayWidth(match[0]),
|
|
369
|
-
scopes: []
|
|
371
|
+
scopes: [],
|
|
372
|
+
trimOnWrap: true
|
|
370
373
|
};
|
|
371
374
|
}
|
|
372
375
|
}
|
|
@@ -383,22 +386,46 @@ function renderMessage(msg, options, theme, ambient) {
|
|
|
383
386
|
}
|
|
384
387
|
const tokens = [];
|
|
385
388
|
let totalWidth = initialWidth;
|
|
386
|
-
|
|
389
|
+
let pendingWrap = false;
|
|
390
|
+
let atWrappedLineStart = false;
|
|
391
|
+
for (let token of stream()) {
|
|
387
392
|
if (token.width === -1) {
|
|
388
393
|
tokens.push(token);
|
|
389
394
|
totalWidth = 0;
|
|
395
|
+
pendingWrap = false;
|
|
396
|
+
atWrappedLineStart = false;
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
const wraps = pendingWrap || options.maxWidth != null && totalWidth > 0 && totalWidth + token.width > options.maxWidth;
|
|
400
|
+
if ((wraps || atWrappedLineStart) && token.trimOnWrap) {
|
|
401
|
+
const text$1 = token.text.trimStart();
|
|
402
|
+
token = {
|
|
403
|
+
...token,
|
|
404
|
+
text: text$1,
|
|
405
|
+
width: token.width - getDisplayWidth(token.text.slice(0, token.text.length - text$1.length))
|
|
406
|
+
};
|
|
407
|
+
if (text$1 === "") {
|
|
408
|
+
if (wraps) pendingWrap = true;
|
|
409
|
+
continue;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
if (pendingWrap && stripAnsi(token.text) === "") {
|
|
413
|
+
tokens.push(token);
|
|
390
414
|
continue;
|
|
391
415
|
}
|
|
392
|
-
if (
|
|
416
|
+
if (wraps) {
|
|
393
417
|
tokens.push({
|
|
394
418
|
text: "\n",
|
|
395
419
|
width: -1,
|
|
396
420
|
scopes: []
|
|
397
421
|
});
|
|
398
422
|
totalWidth = 0;
|
|
423
|
+
pendingWrap = false;
|
|
424
|
+
atWrappedLineStart = true;
|
|
399
425
|
}
|
|
400
426
|
tokens.push(token);
|
|
401
427
|
totalWidth += token.width;
|
|
428
|
+
if (token.width > 0) atWrappedLineStart = false;
|
|
402
429
|
}
|
|
403
430
|
return serializeTokens(tokens, useColors, ambient == null ? resetSuffix : "", ambient);
|
|
404
431
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_displaywidth = require('./displaywidth.cjs');
|
|
2
|
+
const require_terminal_separators = require('./terminal-separators.cjs');
|
|
2
3
|
const require_terminal = require('./terminal.cjs');
|
|
3
4
|
|
|
4
5
|
//#region src/terminal-internal.ts
|
|
@@ -151,6 +152,7 @@ function sameStyle(a, b) {
|
|
|
151
152
|
}
|
|
152
153
|
function* fragmentTokens(fragment, scopes = [], inherited = {}) {
|
|
153
154
|
if (fragment.type === "text") {
|
|
155
|
+
const marks = require_terminal_separators.wrapTrimmableFragments.has(fragment) ? { trimOnWrap: true } : {};
|
|
154
156
|
const lines = fragment.text.split("\n");
|
|
155
157
|
for (let i = 0; i < lines.length; i++) {
|
|
156
158
|
if (i > 0) yield {
|
|
@@ -161,7 +163,8 @@ function* fragmentTokens(fragment, scopes = [], inherited = {}) {
|
|
|
161
163
|
if (lines[i].length > 0 || lines.length === 1) yield {
|
|
162
164
|
text: lines[i],
|
|
163
165
|
width: require_displaywidth.getDisplayWidth(lines[i]),
|
|
164
|
-
scopes
|
|
166
|
+
scopes,
|
|
167
|
+
...marks
|
|
165
168
|
};
|
|
166
169
|
}
|
|
167
170
|
return;
|
|
@@ -16,6 +16,11 @@ interface TerminalToken {
|
|
|
16
16
|
readonly programBoundary?: boolean;
|
|
17
17
|
/** Enables only the legacy default formatter whitespace behavior. */
|
|
18
18
|
readonly legacyWhitespace?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Leading whitespace only separates the token from preceding content, so
|
|
21
|
+
* message wrapping may drop it when the token starts a wrapped line.
|
|
22
|
+
*/
|
|
23
|
+
readonly trimOnWrap?: boolean;
|
|
19
24
|
}
|
|
20
25
|
declare function terminalText(text: string): TerminalFragment;
|
|
21
26
|
declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
|
|
@@ -16,6 +16,11 @@ interface TerminalToken {
|
|
|
16
16
|
readonly programBoundary?: boolean;
|
|
17
17
|
/** Enables only the legacy default formatter whitespace behavior. */
|
|
18
18
|
readonly legacyWhitespace?: boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Leading whitespace only separates the token from preceding content, so
|
|
21
|
+
* message wrapping may drop it when the token starts a wrapped line.
|
|
22
|
+
*/
|
|
23
|
+
readonly trimOnWrap?: boolean;
|
|
19
24
|
}
|
|
20
25
|
declare function terminalText(text: string): TerminalFragment;
|
|
21
26
|
declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getDisplayWidth } from "./displaywidth.js";
|
|
2
|
+
import { wrapTrimmableFragments } from "./terminal-separators.js";
|
|
2
3
|
import { defaultTerminalTheme } from "./terminal.js";
|
|
3
4
|
|
|
4
5
|
//#region src/terminal-internal.ts
|
|
@@ -151,6 +152,7 @@ function sameStyle(a, b) {
|
|
|
151
152
|
}
|
|
152
153
|
function* fragmentTokens(fragment, scopes = [], inherited = {}) {
|
|
153
154
|
if (fragment.type === "text") {
|
|
155
|
+
const marks = wrapTrimmableFragments.has(fragment) ? { trimOnWrap: true } : {};
|
|
154
156
|
const lines = fragment.text.split("\n");
|
|
155
157
|
for (let i = 0; i < lines.length; i++) {
|
|
156
158
|
if (i > 0) yield {
|
|
@@ -161,7 +163,8 @@ function* fragmentTokens(fragment, scopes = [], inherited = {}) {
|
|
|
161
163
|
if (lines[i].length > 0 || lines.length === 1) yield {
|
|
162
164
|
text: lines[i],
|
|
163
165
|
width: getDisplayWidth(lines[i]),
|
|
164
|
-
scopes
|
|
166
|
+
scopes,
|
|
167
|
+
...marks
|
|
165
168
|
};
|
|
166
169
|
}
|
|
167
170
|
return;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/terminal-separators.ts
|
|
3
|
+
/**
|
|
4
|
+
* Text fragments that only separate the items around them, such as the
|
|
5
|
+
* spaces the default `values` formatter puts between values. When message
|
|
6
|
+
* wrapping moves such a fragment to the start of a new line, its leading
|
|
7
|
+
* whitespace may be dropped.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
const wrapTrimmableFragments = /* @__PURE__ */ new WeakSet();
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
exports.wrapTrimmableFragments = wrapTrimmableFragments;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/terminal-separators.ts
|
|
2
|
+
/**
|
|
3
|
+
* Text fragments that only separate the items around them, such as the
|
|
4
|
+
* spaces the default `values` formatter puts between values. When message
|
|
5
|
+
* wrapping moves such a fragment to the start of a new line, its leading
|
|
6
|
+
* whitespace may be dropped.
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
const wrapTrimmableFragments = /* @__PURE__ */ new WeakSet();
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { wrapTrimmableFragments };
|
package/dist/terminal.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const require_terminal_separators = require('./terminal-separators.cjs');
|
|
1
2
|
|
|
2
3
|
//#region src/terminal.ts
|
|
3
4
|
const plain = (text) => ({
|
|
@@ -9,6 +10,8 @@ const styled = (text, style) => ({
|
|
|
9
10
|
style,
|
|
10
11
|
children: [plain(text)]
|
|
11
12
|
});
|
|
13
|
+
const valuesSeparator = plain(" ");
|
|
14
|
+
require_terminal_separators.wrapTrimmableFragments.add(valuesSeparator);
|
|
12
15
|
/**
|
|
13
16
|
* Optique's built-in terminal theme, with every formatter available for delegation.
|
|
14
17
|
* @since 1.3.0
|
|
@@ -34,7 +37,7 @@ const defaultTerminalTheme = {
|
|
|
34
37
|
value: (_term, ctx) => ctx.usage === "literal" ? plain(ctx.text) : styled(ctx.text, { foreground: "green" }),
|
|
35
38
|
values: (term, ctx) => ({
|
|
36
39
|
type: "concat",
|
|
37
|
-
children: term.values.flatMap((value, i) => [...i === 0 ? [] : [
|
|
40
|
+
children: term.values.flatMap((value, i) => [...i === 0 ? [] : [valuesSeparator], ctx.format({
|
|
38
41
|
type: "value",
|
|
39
42
|
value
|
|
40
43
|
})])
|
package/dist/terminal.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { wrapTrimmableFragments } from "./terminal-separators.js";
|
|
2
|
+
|
|
1
3
|
//#region src/terminal.ts
|
|
2
4
|
const plain = (text) => ({
|
|
3
5
|
type: "text",
|
|
@@ -8,6 +10,8 @@ const styled = (text, style) => ({
|
|
|
8
10
|
style,
|
|
9
11
|
children: [plain(text)]
|
|
10
12
|
});
|
|
13
|
+
const valuesSeparator = plain(" ");
|
|
14
|
+
wrapTrimmableFragments.add(valuesSeparator);
|
|
11
15
|
/**
|
|
12
16
|
* Optique's built-in terminal theme, with every formatter available for delegation.
|
|
13
17
|
* @since 1.3.0
|
|
@@ -33,7 +37,7 @@ const defaultTerminalTheme = {
|
|
|
33
37
|
value: (_term, ctx) => ctx.usage === "literal" ? plain(ctx.text) : styled(ctx.text, { foreground: "green" }),
|
|
34
38
|
values: (term, ctx) => ({
|
|
35
39
|
type: "concat",
|
|
36
|
-
children: term.values.flatMap((value, i) => [...i === 0 ? [] : [
|
|
40
|
+
children: term.values.flatMap((value, i) => [...i === 0 ? [] : [valuesSeparator], ctx.format({
|
|
37
41
|
type: "value",
|
|
38
42
|
value
|
|
39
43
|
})])
|
package/dist/text-layout.cjs
CHANGED
|
@@ -51,6 +51,18 @@ function placeText(text, cursor, maxWidth, trailingRoom = 0) {
|
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
const leadingSpacePattern = /^((?:\x1B(?:\[[0-9;:]*[@-~]|\][^\x1B\x07]*(?:\x1B\\|\x07)))*)[^\S\n]+/;
|
|
55
|
+
/**
|
|
56
|
+
* Removes the whitespace that begins a text's first line, keeping any
|
|
57
|
+
* escape sequences before it. Used when layout moves text that starts with
|
|
58
|
+
* a separating space to a fresh line.
|
|
59
|
+
* @param text Rendered text, possibly containing ANSI styles or OSC links.
|
|
60
|
+
* @returns The text without its leading whitespace.
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
function trimLeadingSpace(text) {
|
|
64
|
+
return text.replace(leadingSpacePattern, "$1");
|
|
65
|
+
}
|
|
54
66
|
/**
|
|
55
67
|
* Measures an annotation's fixed text without invoking theme callbacks.
|
|
56
68
|
* @param prefix The already joined prefix and optional label.
|
|
@@ -84,4 +96,5 @@ function spaceAfterLabel(label) {
|
|
|
84
96
|
exports.measureAnnotation = measureAnnotation;
|
|
85
97
|
exports.measureText = measureText;
|
|
86
98
|
exports.placeText = placeText;
|
|
87
|
-
exports.spaceAfterLabel = spaceAfterLabel;
|
|
99
|
+
exports.spaceAfterLabel = spaceAfterLabel;
|
|
100
|
+
exports.trimLeadingSpace = trimLeadingSpace;
|
package/dist/text-layout.d.cts
CHANGED
|
@@ -41,7 +41,14 @@ declare function placeText(text: string, cursor: TextCursor, maxWidth?: number,
|
|
|
41
41
|
readonly text: string;
|
|
42
42
|
readonly cursor: TextCursor;
|
|
43
43
|
};
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Removes the whitespace that begins a text's first line, keeping any
|
|
46
|
+
* escape sequences before it. Used when layout moves text that starts with
|
|
47
|
+
* a separating space to a fresh line.
|
|
48
|
+
* @param text Rendered text, possibly containing ANSI styles or OSC links.
|
|
49
|
+
* @returns The text without its leading whitespace.
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
45
52
|
|
|
46
53
|
/**
|
|
47
54
|
* Adds a separating space only when a label occupies its final physical line.
|
package/dist/text-layout.d.ts
CHANGED
|
@@ -41,7 +41,14 @@ declare function placeText(text: string, cursor: TextCursor, maxWidth?: number,
|
|
|
41
41
|
readonly text: string;
|
|
42
42
|
readonly cursor: TextCursor;
|
|
43
43
|
};
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Removes the whitespace that begins a text's first line, keeping any
|
|
46
|
+
* escape sequences before it. Used when layout moves text that starts with
|
|
47
|
+
* a separating space to a fresh line.
|
|
48
|
+
* @param text Rendered text, possibly containing ANSI styles or OSC links.
|
|
49
|
+
* @returns The text without its leading whitespace.
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
45
52
|
|
|
46
53
|
/**
|
|
47
54
|
* Adds a separating space only when a label occupies its final physical line.
|
package/dist/text-layout.js
CHANGED
|
@@ -51,6 +51,18 @@ function placeText(text, cursor, maxWidth, trailingRoom = 0) {
|
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
|
+
const leadingSpacePattern = /^((?:\x1B(?:\[[0-9;:]*[@-~]|\][^\x1B\x07]*(?:\x1B\\|\x07)))*)[^\S\n]+/;
|
|
55
|
+
/**
|
|
56
|
+
* Removes the whitespace that begins a text's first line, keeping any
|
|
57
|
+
* escape sequences before it. Used when layout moves text that starts with
|
|
58
|
+
* a separating space to a fresh line.
|
|
59
|
+
* @param text Rendered text, possibly containing ANSI styles or OSC links.
|
|
60
|
+
* @returns The text without its leading whitespace.
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
function trimLeadingSpace(text) {
|
|
64
|
+
return text.replace(leadingSpacePattern, "$1");
|
|
65
|
+
}
|
|
54
66
|
/**
|
|
55
67
|
* Measures an annotation's fixed text without invoking theme callbacks.
|
|
56
68
|
* @param prefix The already joined prefix and optional label.
|
|
@@ -81,4 +93,4 @@ function spaceAfterLabel(label) {
|
|
|
81
93
|
}
|
|
82
94
|
|
|
83
95
|
//#endregion
|
|
84
|
-
export { measureAnnotation, measureText, placeText, spaceAfterLabel };
|
|
96
|
+
export { measureAnnotation, measureText, placeText, spaceAfterLabel, trimLeadingSpace };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optique/core",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "Type-safe combinatorial command-line interface parser",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"CLI",
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
},
|
|
238
238
|
"sideEffects": false,
|
|
239
239
|
"devDependencies": {
|
|
240
|
-
"@optique/env": "1.3.
|
|
240
|
+
"@optique/env": "1.3.3",
|
|
241
241
|
"@types/node": "^24.0.0",
|
|
242
242
|
"fast-check": "^4.7.0",
|
|
243
243
|
"tsdown": "^0.13.0",
|