diff options
Diffstat (limited to 'packages/cli/src/ui/utils/textUtils.ts')
| -rw-r--r-- | packages/cli/src/ui/utils/textUtils.ts | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/packages/cli/src/ui/utils/textUtils.ts b/packages/cli/src/ui/utils/textUtils.ts index e4d8ea58..7630f04d 100644 --- a/packages/cli/src/ui/utils/textUtils.ts +++ b/packages/cli/src/ui/utils/textUtils.ts @@ -4,6 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +import stripAnsi from 'strip-ansi'; +import { stripVTControlCharacters } from 'util'; + /** * Calculates the maximum width of a multi-line ASCII art string. * @param asciiArt The ASCII art string. @@ -38,3 +41,48 @@ export function cpSlice(str: string, start: number, end?: number): string { const arr = toCodePoints(str).slice(start, end); return arr.join(''); } + +/** + * Strip characters that can break terminal rendering. + * + * Uses Node.js built-in stripVTControlCharacters to handle VT sequences, + * then filters remaining control characters that can disrupt display. + * + * Characters stripped: + * - ANSI escape sequences (via strip-ansi) + * - VT control sequences (via Node.js util.stripVTControlCharacters) + * - C0 control chars (0x00-0x1F) except CR/LF which are handled elsewhere + * - C1 control chars (0x80-0x9F) that can cause display issues + * + * Characters preserved: + * - All printable Unicode including emojis + * - DEL (0x7F) - handled functionally by applyOperations, not a display issue + * - CR/LF (0x0D/0x0A) - needed for line breaks + */ +export function stripUnsafeCharacters(str: string): string { + const strippedAnsi = stripAnsi(str); + const strippedVT = stripVTControlCharacters(strippedAnsi); + + return toCodePoints(strippedVT) + .filter((char) => { + const code = char.codePointAt(0); + if (code === undefined) return false; + + // Preserve CR/LF for line handling + if (code === 0x0a || code === 0x0d) return true; + + // Remove C0 control chars (except CR/LF) that can break display + // Examples: BELL(0x07) makes noise, BS(0x08) moves cursor, VT(0x0B), FF(0x0C) + if (code >= 0x00 && code <= 0x1f) return false; + + // Remove C1 control chars (0x80-0x9f) - legacy 8-bit control codes + if (code >= 0x80 && code <= 0x9f) return false; + + // Preserve DEL (0x7f) - it's handled functionally by applyOperations as backspace + // and doesn't cause rendering issues when displayed + + // Preserve all other characters including Unicode/emojis + return true; + }) + .join(''); +} |
