fix(parse): strip OSC escape sequences in StripAnsi for backwards compat

This commit is contained in:
Mortdecai
2026-04-07 20:05:16 -04:00
parent b3bbd55551
commit 84018efbbf
2 changed files with 73 additions and 1 deletions
+5 -1
View File
@@ -11,7 +11,11 @@ import (
"git.sr.ht/~rjarry/aerc/lib/log" "git.sr.ht/~rjarry/aerc/lib/log"
) )
var AnsiReg = regexp.MustCompile("\x1B\\[[0-?]*[ -/]*[@-~]") var AnsiReg = regexp.MustCompile(
`\x1B\[[0-?]*[ -/]*[@-~]` + // CSI sequences: ESC [ ... final_byte
`|` +
`\x1B\][^\x07\x1B]*(?:\x07|\x1B\\)`, // OSC sequences: ESC ] ... (BEL | ESC \)
)
// StripAnsi strips ansi escape codes from the reader // StripAnsi strips ansi escape codes from the reader
func StripAnsi(r io.Reader) io.Reader { func StripAnsi(r io.Reader) io.Reader {
+68
View File
@@ -0,0 +1,68 @@
package parse
import (
"io"
"strings"
"testing"
)
func TestStripAnsi_CSI(t *testing.T) {
input := "Hello \033[31mred\033[0m world\n"
r := StripAnsi(strings.NewReader(input))
out, _ := io.ReadAll(r)
if string(out) != "Hello red world\n" {
t.Errorf("got %q", string(out))
}
}
func TestStripAnsi_OSC9ImageMarker(t *testing.T) {
input := "Before\n\033]9;image:path=/tmp/img.png;alt=photo\007\nAfter\n"
r := StripAnsi(strings.NewReader(input))
out, _ := io.ReadAll(r)
expected := "Before\n\nAfter\n"
if string(out) != expected {
t.Errorf("got %q, want %q", string(out), expected)
}
}
func TestStripAnsi_OSCWithEscBackslash(t *testing.T) {
input := "Text \033]9;image:path=/tmp/x.png\033\\ more\n"
r := StripAnsi(strings.NewReader(input))
out, _ := io.ReadAll(r)
if strings.Contains(string(out), "\033") {
t.Errorf("OSC not stripped: %q", string(out))
}
}
func TestStripAnsi_OSC8Hyperlink(t *testing.T) {
input := "\033]8;;https://example.com\033\\click\033]8;;\033\\\n"
r := StripAnsi(strings.NewReader(input))
out, _ := io.ReadAll(r)
if strings.Contains(string(out), "\033") {
t.Errorf("OSC 8 not stripped: %q", string(out))
}
if !strings.Contains(string(out), "click") {
t.Error("visible text lost")
}
}
func TestStripAnsi_PlainText(t *testing.T) {
input := "No escape sequences here\n"
r := StripAnsi(strings.NewReader(input))
out, _ := io.ReadAll(r)
if string(out) != input {
t.Errorf("got %q", string(out))
}
}
func TestStripAnsi_MixedCSIAndOSC(t *testing.T) {
input := "\033[1mBold\033[0m \033]9;image:path=/tmp/a.png\007 text\n"
r := StripAnsi(strings.NewReader(input))
out, _ := io.ReadAll(r)
if strings.Contains(string(out), "\033") {
t.Errorf("escape sequences remain: %q", string(out))
}
if !strings.Contains(string(out), "Bold") || !strings.Contains(string(out), "text") {
t.Error("visible text lost")
}
}