Files
aerc-inline-images/lib/parse/extract_images.go
T
Mortdecai 9fd718b2ae fix(msgviewer): use pager for all text, replace image markers with readable placeholders
The composite renderer bypassed the pager (less) for any email with images,
losing colors, scrolling, and search. Now always forward to the pager with
[image: alt] text placeholders. Image refs are still extracted and stored
for future inline rendering.
2026-04-07 20:58:45 -04:00

72 lines
1.9 KiB
Go

package parse
import (
"bufio"
"bytes"
"fmt"
"io"
"git.sr.ht/~rjarry/aerc/lib/log"
)
// ExtractImages scans a reader for OSC 9 image markers, replaces them with
// null-byte-delimited placeholders (\x00IMG:N\x00), and returns the cleaned
// reader plus a slice of ImageRef structs.
//
// Lines containing valid image markers are replaced entirely with the
// placeholder. Lines with invalid markers (e.g. missing path) pass through
// unchanged.
func ExtractImages(r io.Reader) (io.Reader, []ImageRef) {
var images []ImageRef
buf := bytes.NewBuffer(nil)
scanner := bufio.NewScanner(r)
scanner.Buffer(nil, 1024*1024*1024)
for scanner.Scan() {
line := scanner.Bytes()
if bytes.Contains(line, oscImagePrefix) {
if ref, ok := ParseImageOSC(line); ok {
ref.Index = len(images)
images = append(images, *ref)
fmt.Fprintf(buf, "\x00IMG:%d\x00\n", ref.Index)
continue
}
}
buf.Write(line)
buf.WriteByte('\n')
}
if err := scanner.Err(); err != nil {
log.Warnf("ExtractImages: scan error: %v", err)
}
return buf, images
}
// ReplacePlaceholders converts \x00IMG:N\x00 placeholders into human-readable
// [image: alt] text suitable for display in a pager.
func ReplacePlaceholders(data []byte, images []ImageRef) []byte {
result := bytes.NewBuffer(nil)
for _, line := range bytes.Split(data, []byte("\n")) {
trimmed := bytes.TrimSpace(line)
if len(trimmed) > 6 && trimmed[0] == 0 &&
bytes.HasPrefix(trimmed, []byte("\x00IMG:")) &&
trimmed[len(trimmed)-1] == 0 {
// Extract index
numStr := string(trimmed[5 : len(trimmed)-1])
idx := 0
for _, c := range numStr {
if c >= '0' && c <= '9' {
idx = idx*10 + int(c-'0')
}
}
if idx < len(images) && images[idx].Alt != "" {
fmt.Fprintf(result, "[image: %s]\n", images[idx].Alt)
} else {
result.WriteString("[image]\n")
}
} else {
result.Write(line)
result.WriteByte('\n')
}
}
return result.Bytes()
}