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 {