From 05651d4bd5ca5a6da7ff74f903b3fb3ad210e55b Mon Sep 17 00:00:00 2001 From: Drew Smirnoff Date: Thu, 7 May 2026 15:30:25 +0400 Subject: [PATCH] fix: split pane html conv and table fix (#1246) ## What? Fixes split pane HTML conversion, according to #1213 Also changes in `view/html.go`: - Extracted element loop into `renderHTMLToText` helper. - `processBody` now: if `mimeType == text/html` and direct render is whitespace-only, retry through `markdownToHTML` pre-pass ## Why? Certain emails are not displayed correctly, as pointed by @EmilyxFox. Also, split pane was displaying emails incorrectly not as per #1213 fix. Signed-off-by: drew --- tui/folder_inbox.go | 1 + view/html.go | 30 +++++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/tui/folder_inbox.go b/tui/folder_inbox.go index 2969fba3b341dd68960d67cc71646cbc8aabf9be..3069d87b95e06665fc3b99dd455b20365e1e56e2 100644 --- a/tui/folder_inbox.go +++ b/tui/folder_inbox.go @@ -353,6 +353,7 @@ func (m *FolderInbox) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } // Update email with body email.Body = msg.Body + email.BodyMIMEType = msg.BodyMIMEType email.Attachments = msg.Attachments // Create preview pane with column offset for image rendering previewWidth := m.calculatePreviewWidth() diff --git a/view/html.go b/view/html.go index 8644980fb48a1aaed6facf7fe4f31769710b7398..feaff04472f774c079f4b52c00f011c16eae2e39 100644 --- a/view/html.go +++ b/view/html.go @@ -703,13 +703,36 @@ func processBody(rawBody, mimeType string, inline map[string]string, h1Style, h2 // HTML bodies skip the markdown pre-pass — md4c can mangle attribute-heavy // or indented HTML (#602-style raw-tag bleed-through). Empty mimeType keeps // legacy behavior for cached/legacy callers that don't supply one. + directHTML := mimeType == BodyMIMETypeHTML var htmlBody []byte - if mimeType == BodyMIMETypeHTML { + if directHTML { htmlBody = []byte(decodedBody) } else { htmlBody = markdownToHTML([]byte(decodedBody)) } + result, placements, err := renderHTMLToText(htmlBody, inline, h1Style, h2Style, disableImages) + if err != nil { + return "", nil, err + } + + // Some real-world HTML emails (newsletters with table-only layouts and no + // , AWeber-shape bodies) emit no visible content from htmlconv. Pre- + // c11de45, every body went through markdownToHTML first, which happened to + // keep these alive. Retry through the markdown pre-pass when the direct + // HTML path produces nothing. + if directHTML && strings.TrimSpace(result) == "" { + result, placements, err = renderHTMLToText(markdownToHTML([]byte(decodedBody)), inline, h1Style, h2Style, disableImages) + if err != nil { + return "", nil, err + } + } + + result = styleQuotedReplies(result) + return bodyStyle.Render(result), placements, nil +} + +func renderHTMLToText(htmlBody []byte, inline map[string]string, h1Style, h2Style lipgloss.Style, disableImages bool) (string, []ImagePlacement, error) { // Parse HTML into structured elements using C parser. elements, ok := clib.HTMLToElements(string(htmlBody)) if !ok { @@ -849,10 +872,7 @@ func processBody(rawBody, mimeType string, inline map[string]string, h1Style, h2 result = imgMarkerRegex.ReplaceAllString(result, "") } - // Style quoted reply sections (for plain text > quotes) - result = styleQuotedReplies(result) - - return bodyStyle.Render(result), placements, nil + return result, placements, nil } func tableHeaderStyle() lipgloss.Style {