@silvery/term 0.3.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.
- package/package.json +54 -0
- package/src/adapters/canvas-adapter.ts +356 -0
- package/src/adapters/dom-adapter.ts +452 -0
- package/src/adapters/flexily-zero-adapter.ts +368 -0
- package/src/adapters/terminal-adapter.ts +305 -0
- package/src/adapters/yoga-adapter.ts +370 -0
- package/src/ansi/ansi.ts +251 -0
- package/src/ansi/constants.ts +76 -0
- package/src/ansi/detection.ts +441 -0
- package/src/ansi/hyperlink.ts +38 -0
- package/src/ansi/index.ts +201 -0
- package/src/ansi/patch-console.ts +159 -0
- package/src/ansi/sgr-codes.ts +34 -0
- package/src/ansi/storybook.ts +209 -0
- package/src/ansi/term.ts +724 -0
- package/src/ansi/types.ts +202 -0
- package/src/ansi/underline.ts +156 -0
- package/src/ansi/utils.ts +65 -0
- package/src/ansi-sanitize.ts +509 -0
- package/src/app.ts +571 -0
- package/src/bound-term.ts +94 -0
- package/src/bracketed-paste.ts +75 -0
- package/src/browser-renderer.ts +174 -0
- package/src/buffer.ts +1984 -0
- package/src/clipboard.ts +74 -0
- package/src/cursor-query.ts +85 -0
- package/src/device-attrs.ts +228 -0
- package/src/devtools.ts +123 -0
- package/src/dom/index.ts +194 -0
- package/src/errors.ts +39 -0
- package/src/focus-reporting.ts +48 -0
- package/src/hit-registry-core.ts +228 -0
- package/src/hit-registry.ts +176 -0
- package/src/index.ts +458 -0
- package/src/input.ts +119 -0
- package/src/inspector.ts +155 -0
- package/src/kitty-detect.ts +95 -0
- package/src/kitty-manager.ts +160 -0
- package/src/layout-engine.ts +296 -0
- package/src/layout.ts +26 -0
- package/src/measurer.ts +74 -0
- package/src/mode-query.ts +106 -0
- package/src/mouse-events.ts +419 -0
- package/src/mouse.ts +83 -0
- package/src/non-tty.ts +223 -0
- package/src/osc-markers.ts +32 -0
- package/src/osc-palette.ts +169 -0
- package/src/output.ts +406 -0
- package/src/pane-manager.ts +248 -0
- package/src/pipeline/CLAUDE.md +587 -0
- package/src/pipeline/content-phase-adapter.ts +976 -0
- package/src/pipeline/content-phase.ts +1765 -0
- package/src/pipeline/helpers.ts +42 -0
- package/src/pipeline/index.ts +416 -0
- package/src/pipeline/layout-phase.ts +686 -0
- package/src/pipeline/measure-phase.ts +198 -0
- package/src/pipeline/measure-stats.ts +21 -0
- package/src/pipeline/output-phase.ts +2593 -0
- package/src/pipeline/render-box.ts +343 -0
- package/src/pipeline/render-helpers.ts +243 -0
- package/src/pipeline/render-text.ts +1255 -0
- package/src/pipeline/types.ts +161 -0
- package/src/pipeline.ts +29 -0
- package/src/pixel-size.ts +119 -0
- package/src/render-adapter.ts +179 -0
- package/src/renderer.ts +1330 -0
- package/src/runtime/create-app.tsx +1845 -0
- package/src/runtime/create-buffer.ts +18 -0
- package/src/runtime/create-runtime.ts +325 -0
- package/src/runtime/diff.ts +56 -0
- package/src/runtime/event-handlers.ts +254 -0
- package/src/runtime/index.ts +119 -0
- package/src/runtime/keys.ts +8 -0
- package/src/runtime/layout.ts +164 -0
- package/src/runtime/run.tsx +318 -0
- package/src/runtime/term-provider.ts +399 -0
- package/src/runtime/terminal-lifecycle.ts +246 -0
- package/src/runtime/tick.ts +219 -0
- package/src/runtime/types.ts +210 -0
- package/src/scheduler.ts +723 -0
- package/src/screenshot.ts +57 -0
- package/src/scroll-region.ts +69 -0
- package/src/scroll-utils.ts +97 -0
- package/src/term-def.ts +267 -0
- package/src/terminal-caps.ts +5 -0
- package/src/terminal-colors.ts +216 -0
- package/src/termtest.ts +224 -0
- package/src/text-sizing.ts +109 -0
- package/src/toolbelt/index.ts +72 -0
- package/src/unicode.ts +1763 -0
- package/src/xterm/index.ts +491 -0
- package/src/xterm/xterm-provider.ts +204 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for @silvery/ansi
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { TerminalCaps } from "./detection"
|
|
6
|
+
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// Color Types
|
|
9
|
+
// =============================================================================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Color level supported by terminal.
|
|
13
|
+
* - 'basic': 16 colors (SGR 30-37, 40-47)
|
|
14
|
+
* - '256': 256 colors (SGR 38;5;n)
|
|
15
|
+
* - 'truecolor': 16M colors (SGR 38;2;r;g;b)
|
|
16
|
+
*/
|
|
17
|
+
export type ColorLevel = "basic" | "256" | "truecolor"
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* RGB color tuple for underline color.
|
|
21
|
+
* Each component is 0-255.
|
|
22
|
+
*/
|
|
23
|
+
export type RGB = [r: number, g: number, b: number]
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Standard ANSI color names (the 16 base colors).
|
|
27
|
+
* These map to SGR 30-37 (foreground) and 40-47 (background),
|
|
28
|
+
* plus their bright variants (SGR 90-97, 100-107).
|
|
29
|
+
*/
|
|
30
|
+
export type AnsiColorName =
|
|
31
|
+
| "black"
|
|
32
|
+
| "red"
|
|
33
|
+
| "green"
|
|
34
|
+
| "yellow"
|
|
35
|
+
| "blue"
|
|
36
|
+
| "magenta"
|
|
37
|
+
| "cyan"
|
|
38
|
+
| "white"
|
|
39
|
+
| "gray"
|
|
40
|
+
| "grey"
|
|
41
|
+
| "blackBright"
|
|
42
|
+
| "redBright"
|
|
43
|
+
| "greenBright"
|
|
44
|
+
| "yellowBright"
|
|
45
|
+
| "blueBright"
|
|
46
|
+
| "magentaBright"
|
|
47
|
+
| "cyanBright"
|
|
48
|
+
| "whiteBright"
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Hex color string pattern.
|
|
52
|
+
* Accepts 3-digit (#rgb) and 6-digit (#rrggbb) hex colors.
|
|
53
|
+
*/
|
|
54
|
+
type HexColor = `#${string}`
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* RGB function-style color string pattern.
|
|
58
|
+
* Format: rgb(r,g,b) where r, g, b are 0-255.
|
|
59
|
+
*/
|
|
60
|
+
type RgbColor = `rgb(${string})`
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Theme token color string pattern.
|
|
64
|
+
* Format: $name — resolved against the active theme at render time.
|
|
65
|
+
* Examples: $primary, $surface, $error, $bg, $fg, $muted
|
|
66
|
+
*/
|
|
67
|
+
type ThemeToken = `$${string}`
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Type-safe color value accepted by ansi APIs.
|
|
71
|
+
*
|
|
72
|
+
* Accepts:
|
|
73
|
+
* - ANSI color names: `"red"`, `"cyan"`, `"whiteBright"`, etc.
|
|
74
|
+
* - Hex colors: `"#ff0000"`, `"#f00"`
|
|
75
|
+
* - RGB function: `"rgb(255, 0, 0)"`
|
|
76
|
+
* - Theme tokens: `"$primary"`, `"$error"`, `"$surface"`
|
|
77
|
+
* - Any other string (for forward compatibility with custom color schemes)
|
|
78
|
+
*
|
|
79
|
+
* The union of known literals provides autocompletion in editors while
|
|
80
|
+
* the `string & {}` fallback allows arbitrary color strings.
|
|
81
|
+
*/
|
|
82
|
+
export type Color = AnsiColorName | HexColor | RgbColor | ThemeToken | (string & {})
|
|
83
|
+
|
|
84
|
+
// =============================================================================
|
|
85
|
+
// Underline Types
|
|
86
|
+
// =============================================================================
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Extended underline styles supported by modern terminals.
|
|
90
|
+
*
|
|
91
|
+
* - `single`: Standard underline (SGR 4:1)
|
|
92
|
+
* - `double`: Two parallel lines (SGR 4:2)
|
|
93
|
+
* - `curly`: Wavy/squiggly line (SGR 4:3) - commonly used for spell check
|
|
94
|
+
* - `dotted`: Dotted line (SGR 4:4)
|
|
95
|
+
* - `dashed`: Dashed line (SGR 4:5)
|
|
96
|
+
*/
|
|
97
|
+
export type UnderlineStyle = "single" | "double" | "curly" | "dotted" | "dashed"
|
|
98
|
+
|
|
99
|
+
// =============================================================================
|
|
100
|
+
// Style Types
|
|
101
|
+
// =============================================================================
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Style options for term.style() method.
|
|
105
|
+
*/
|
|
106
|
+
export interface StyleOptions {
|
|
107
|
+
color?: Color
|
|
108
|
+
bgColor?: Color
|
|
109
|
+
bold?: boolean
|
|
110
|
+
dim?: boolean
|
|
111
|
+
italic?: boolean
|
|
112
|
+
underline?: boolean
|
|
113
|
+
strikethrough?: boolean
|
|
114
|
+
inverse?: boolean
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// =============================================================================
|
|
118
|
+
// Console Types
|
|
119
|
+
// =============================================================================
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Console method names that can be intercepted.
|
|
123
|
+
*/
|
|
124
|
+
export type ConsoleMethod = "log" | "info" | "warn" | "error" | "debug"
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Entry captured from console.
|
|
128
|
+
*/
|
|
129
|
+
export interface ConsoleEntry {
|
|
130
|
+
method: ConsoleMethod
|
|
131
|
+
args: unknown[]
|
|
132
|
+
stream: "stdout" | "stderr"
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// =============================================================================
|
|
136
|
+
// Term Types
|
|
137
|
+
// =============================================================================
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Options for createTerm().
|
|
141
|
+
*/
|
|
142
|
+
export interface CreateTermOptions {
|
|
143
|
+
stdout?: NodeJS.WriteStream
|
|
144
|
+
stdin?: NodeJS.ReadStream
|
|
145
|
+
|
|
146
|
+
// Override auto-detection (for testing or forcing)
|
|
147
|
+
color?: ColorLevel | null // override hasColor()
|
|
148
|
+
unicode?: boolean // override hasUnicode()
|
|
149
|
+
cursor?: boolean // override hasCursor()
|
|
150
|
+
|
|
151
|
+
// Terminal capabilities override
|
|
152
|
+
caps?: Partial<TerminalCaps>
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Re-export TerminalCaps from detection for convenience
|
|
156
|
+
export type { TerminalCaps } from "./detection"
|
|
157
|
+
|
|
158
|
+
// =============================================================================
|
|
159
|
+
// Terminal Emulator Types (duck-types for termless integration)
|
|
160
|
+
// =============================================================================
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* A screen region — duck-type matching termless RegionView.
|
|
164
|
+
* Provides text content and line access for assertions.
|
|
165
|
+
*/
|
|
166
|
+
export interface TermScreen {
|
|
167
|
+
getText(): string
|
|
168
|
+
getLines(): string[]
|
|
169
|
+
containsText?(text: string): boolean
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* A terminal emulator — duck-type matching termless Terminal.
|
|
174
|
+
* Accepts ANSI output, provides screen/scrollback for inspection.
|
|
175
|
+
*/
|
|
176
|
+
export interface TermEmulator {
|
|
177
|
+
readonly cols: number
|
|
178
|
+
readonly rows: number
|
|
179
|
+
readonly screen: TermScreen
|
|
180
|
+
readonly scrollback: TermScreen
|
|
181
|
+
feed(data: Uint8Array | string): void
|
|
182
|
+
resize(cols: number, rows: number): void
|
|
183
|
+
close(): Promise<void>
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* A terminal emulator backend — duck-type matching termless TerminalBackend.
|
|
188
|
+
* Raw backend that needs initialization. Pass to createTerm(backend, { cols, rows }).
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* ```ts
|
|
192
|
+
* import { createXtermBackend } from "@termless/xtermjs"
|
|
193
|
+
* using term = createTerm(createXtermBackend(), { cols: 80, rows: 24 })
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
196
|
+
export interface TermEmulatorBackend {
|
|
197
|
+
readonly name: string
|
|
198
|
+
init(opts: { cols: number; rows: number; scrollbackLimit?: number }): void
|
|
199
|
+
destroy(): void
|
|
200
|
+
feed(data: Uint8Array): void
|
|
201
|
+
resize(cols: number, rows: number): void
|
|
202
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extended underline style functions.
|
|
3
|
+
*
|
|
4
|
+
* Provides curly, dotted, dashed, and double underline styles
|
|
5
|
+
* with graceful fallback to standard underline on unsupported terminals.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import chalk from "chalk"
|
|
9
|
+
import {
|
|
10
|
+
UNDERLINE_CODES,
|
|
11
|
+
UNDERLINE_COLOR_RESET,
|
|
12
|
+
UNDERLINE_STANDARD,
|
|
13
|
+
UNDERLINE_RESET_STANDARD,
|
|
14
|
+
buildUnderlineColorCode,
|
|
15
|
+
} from "./constants"
|
|
16
|
+
import { detectExtendedUnderline } from "./detection"
|
|
17
|
+
import type { UnderlineStyle, RGB } from "./types"
|
|
18
|
+
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Extended Underline Functions
|
|
21
|
+
// =============================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Apply an extended underline style to text.
|
|
25
|
+
* Falls back to regular underline on unsupported terminals.
|
|
26
|
+
*
|
|
27
|
+
* @param text - Text to underline
|
|
28
|
+
* @param style - Underline style (default: "single")
|
|
29
|
+
* @returns Styled text with ANSI codes
|
|
30
|
+
*/
|
|
31
|
+
export function underline(text: string, style: UnderlineStyle = "single"): string {
|
|
32
|
+
if (!detectExtendedUnderline() || style === "single") {
|
|
33
|
+
return chalk.underline(text)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return `${UNDERLINE_CODES[style]}${text}${UNDERLINE_CODES.reset}`
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Apply curly/wavy underline to text.
|
|
41
|
+
* Commonly used for spell check errors in IDEs.
|
|
42
|
+
* Falls back to regular underline on unsupported terminals.
|
|
43
|
+
*
|
|
44
|
+
* @param text - Text to underline
|
|
45
|
+
* @returns Styled text with curly underline
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* import { curlyUnderline, chalk } from '@silvery/ansi';
|
|
50
|
+
*
|
|
51
|
+
* console.log(curlyUnderline('misspelled'));
|
|
52
|
+
* console.log(chalk.red(curlyUnderline('error')));
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export function curlyUnderline(text: string): string {
|
|
56
|
+
return underline(text, "curly")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Apply dotted underline to text.
|
|
61
|
+
* Falls back to regular underline on unsupported terminals.
|
|
62
|
+
*
|
|
63
|
+
* @param text - Text to underline
|
|
64
|
+
* @returns Styled text with dotted underline
|
|
65
|
+
*/
|
|
66
|
+
export function dottedUnderline(text: string): string {
|
|
67
|
+
return underline(text, "dotted")
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Apply dashed underline to text.
|
|
72
|
+
* Falls back to regular underline on unsupported terminals.
|
|
73
|
+
*
|
|
74
|
+
* @param text - Text to underline
|
|
75
|
+
* @returns Styled text with dashed underline
|
|
76
|
+
*/
|
|
77
|
+
export function dashedUnderline(text: string): string {
|
|
78
|
+
return underline(text, "dashed")
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Apply double underline to text.
|
|
83
|
+
* Falls back to regular underline on unsupported terminals.
|
|
84
|
+
*
|
|
85
|
+
* @param text - Text to underline
|
|
86
|
+
* @returns Styled text with double underline
|
|
87
|
+
*/
|
|
88
|
+
export function doubleUnderline(text: string): string {
|
|
89
|
+
return underline(text, "double")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// =============================================================================
|
|
93
|
+
// Underline Color Functions
|
|
94
|
+
// =============================================================================
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Set underline color independently of text color.
|
|
98
|
+
* On unsupported terminals, the color is ignored but underline still applies.
|
|
99
|
+
*
|
|
100
|
+
* @param r - Red component (0-255)
|
|
101
|
+
* @param g - Green component (0-255)
|
|
102
|
+
* @param b - Blue component (0-255)
|
|
103
|
+
* @param text - Text to style
|
|
104
|
+
* @returns Styled text with colored underline
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```ts
|
|
108
|
+
* import { underlineColor, chalk } from '@silvery/ansi';
|
|
109
|
+
*
|
|
110
|
+
* // Red underline (text color unchanged)
|
|
111
|
+
* console.log(underlineColor(255, 0, 0, 'warning'));
|
|
112
|
+
*
|
|
113
|
+
* // Red underline with blue text
|
|
114
|
+
* console.log(chalk.blue(underlineColor(255, 0, 0, 'blue text, red underline')));
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export function underlineColor(r: number, g: number, b: number, text: string): string {
|
|
118
|
+
if (!detectExtendedUnderline()) {
|
|
119
|
+
// Fallback: just apply regular underline, ignore color
|
|
120
|
+
return chalk.underline(text)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const colorCode = buildUnderlineColorCode(r, g, b)
|
|
124
|
+
return `${UNDERLINE_STANDARD}${colorCode}${text}${UNDERLINE_COLOR_RESET}${UNDERLINE_RESET_STANDARD}`
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Combine underline style with underline color.
|
|
129
|
+
*
|
|
130
|
+
* @param style - Underline style ('curly', 'dotted', 'dashed', 'double', 'single')
|
|
131
|
+
* @param rgb - Color as [r, g, b] tuple (0-255 each)
|
|
132
|
+
* @param text - Text to style
|
|
133
|
+
* @returns Styled text with colored underline in specified style
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```ts
|
|
137
|
+
* import { styledUnderline, chalk } from '@silvery/ansi';
|
|
138
|
+
*
|
|
139
|
+
* // Red curly underline (spell-check style)
|
|
140
|
+
* console.log(styledUnderline('curly', [255, 0, 0], 'misspelled'));
|
|
141
|
+
*
|
|
142
|
+
* // Orange dashed underline with yellow text
|
|
143
|
+
* console.log(chalk.yellow(styledUnderline('dashed', [255, 165, 0], 'warning')));
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export function styledUnderline(style: UnderlineStyle, rgb: RGB, text: string): string {
|
|
147
|
+
if (!detectExtendedUnderline()) {
|
|
148
|
+
return chalk.underline(text)
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const [r, g, b] = rgb
|
|
152
|
+
const styleCode = UNDERLINE_CODES[style]
|
|
153
|
+
const colorCode = buildUnderlineColorCode(r, g, b)
|
|
154
|
+
|
|
155
|
+
return `${styleCode}${colorCode}${text}${UNDERLINE_CODES.reset}${UNDERLINE_COLOR_RESET}`
|
|
156
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI string utilities.
|
|
3
|
+
*
|
|
4
|
+
* This module can be imported separately via `@silvery/ansi/utils`
|
|
5
|
+
* for projects that only need ANSI stripping without chalk.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import stringWidth from "string-width"
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// ANSI Regex Pattern
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* ANSI escape code pattern for stripping.
|
|
16
|
+
*
|
|
17
|
+
* Matches:
|
|
18
|
+
* - ESC CSI SGR sequences: \x1b[31m, \x1b[4:3m, \x1b[38:2::255:100:0m
|
|
19
|
+
* - C1 CSI SGR sequences: \x9b31m, \x9b4:3m
|
|
20
|
+
* - ESC OSC 8 hyperlinks (BEL-terminated): \x1b]8;;<url>\x07
|
|
21
|
+
* - ESC OSC 8 hyperlinks (ST-terminated): \x1b]8;;<url>\x1b\\
|
|
22
|
+
* - C1 OSC 8 hyperlinks (BEL-terminated): \x9d8;;<url>\x07
|
|
23
|
+
* - C1 OSC 8 hyperlinks (ST-terminated): \x9d8;;<url>\x1b\\
|
|
24
|
+
* - C1 OSC 8 hyperlinks (C1 ST-terminated): \x9d8;;<url>\x9c
|
|
25
|
+
*/
|
|
26
|
+
export const ANSI_REGEX =
|
|
27
|
+
/\x1b\[[0-9;:]*m|\x9b[0-9;:]*m|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)|\x9d8;;[^\x07\x1b\x9c]*(?:\x07|\x1b\\|\x9c)/g
|
|
28
|
+
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// String Utilities
|
|
31
|
+
// =============================================================================
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Strip all ANSI escape codes from a string.
|
|
35
|
+
*
|
|
36
|
+
* @param text - String potentially containing ANSI codes
|
|
37
|
+
* @returns Clean string with all ANSI codes removed
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```ts
|
|
41
|
+
* stripAnsi('\x1b[31mred\x1b[0m') // 'red'
|
|
42
|
+
* stripAnsi('\x1b[4:3mwavy\x1b[4:0m') // 'wavy'
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export function stripAnsi(text: string): string {
|
|
46
|
+
return text.replace(ANSI_REGEX, "")
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get the display width of a string, excluding ANSI escape codes.
|
|
51
|
+
* Correctly handles CJK characters, emoji, and other wide characters.
|
|
52
|
+
*
|
|
53
|
+
* @param text - String potentially containing ANSI codes
|
|
54
|
+
* @returns Number of terminal columns the text will occupy
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* displayLength('\x1b[31mhello\x1b[0m') // 5
|
|
59
|
+
* displayLength('hello') // 5
|
|
60
|
+
* displayLength('한글') // 4 (2 chars × 2 cells each)
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function displayLength(text: string): number {
|
|
64
|
+
return stringWidth(stripAnsi(text))
|
|
65
|
+
}
|