diff --git a/.byline/commits/4a477a05f.json b/.byline/commits/4a477a05f.json new file mode 100644 index 0000000..d354376 --- /dev/null +++ b/.byline/commits/4a477a05f.json @@ -0,0 +1,44 @@ +{ + "sha": "4a477a05f2f16b649211e2c77ad9e1c8c7f6e777", + "shortSha": "4a477a05f", + "parentSha": "0d0d95a00c41d5f05ecadf22f44788bd5163b2fc", + "timestamp": "2026-04-21T21:42:31-04:00", + "message": "Add byline commit classification cache files", + "files": { + ".byline/commits/0d0d95a00.json": { + "path": ".byline/commits/0d0d95a00.json", + "summary": { + "mine": 2214, + "machine": 0, + "ours": 0 + }, + "segments": [] + }, + ".byline/commits/c9f2e83f2.json": { + "path": ".byline/commits/c9f2e83f2.json", + "summary": { + "mine": 1379, + "machine": 0, + "ours": 0 + }, + "segments": [] + } + }, + "totals": { + "mine": 3593, + "machine": 0, + "ours": 0, + "percent": { + "mine": 100, + "machine": 0, + "ours": 0 + } + }, + "sessions": [], + "meta": { + "analyzedAt": "2026-04-22T01:42:31.526Z", + "version": "0.2.0", + "retroactive": false, + "confidence": 1 + } +} \ No newline at end of file diff --git a/internal/cmd/gmail_messages.go b/internal/cmd/gmail_messages.go index 3097f46..50588f5 100644 --- a/internal/cmd/gmail_messages.go +++ b/internal/cmd/gmail_messages.go @@ -28,6 +28,7 @@ type GmailMessagesSearchCmd struct { Timezone string `name:"timezone" short:"z" help:"Output timezone (IANA name, e.g. America/New_York, UTC). Default: local"` Local bool `name:"local" help:"Use local timezone (default behavior, useful to override --timezone)"` IncludeBody bool `name:"include-body" help:"Include decoded message body (JSON is full; text output is truncated)"` + BodyFormat string `name:"body-format" help:"Body format preference: text (default) or html" default:"text" enum:"text,html"` Full bool `name:"full" help:"Show full message bodies without truncation (implies --include-body)"` } @@ -88,7 +89,7 @@ func (c *GmailMessagesSearchCmd) Run(ctx context.Context, flags *RootFlags) erro return err } - items, err := fetchMessageDetails(ctx, svc, messages, idToName, loc, c.IncludeBody) + items, err := fetchMessageDetails(ctx, svc, messages, idToName, loc, c.IncludeBody, c.BodyFormat) if err != nil { return err } @@ -200,7 +201,8 @@ type messageItem struct { Body string `json:"body,omitempty"` } -func fetchMessageDetails(ctx context.Context, svc *gmail.Service, messages []*gmail.Message, idToName map[string]string, loc *time.Location, includeBody bool) ([]messageItem, error) { +func fetchMessageDetails(ctx context.Context, svc *gmail.Service, messages []*gmail.Message, idToName map[string]string, loc *time.Location, includeBody bool, bodyFormat ...string) ([]messageItem, error) { + preferHTML := len(bodyFormat) > 0 && bodyFormat[0] == "html" if len(messages) == 0 { return nil, nil } @@ -257,7 +259,11 @@ func fetchMessageDetails(ctx context.Context, svc *gmail.Service, messages []*gm item.Subject = sanitizeTab(headerValue(msg.Payload, "Subject")) item.Date = formatGmailDateInLocation(headerValue(msg.Payload, "Date"), loc) if includeBody { - item.Body = bestBodyText(msg.Payload) + if preferHTML { + item.Body = bestBodyHTML(msg.Payload) + } else { + item.Body = bestBodyText(msg.Payload) + } } if len(msg.LabelIds) > 0 { diff --git a/internal/cmd/gmail_thread.go b/internal/cmd/gmail_thread.go index a72fadd..02e534d 100644 --- a/internal/cmd/gmail_thread.go +++ b/internal/cmd/gmail_thread.go @@ -377,6 +377,18 @@ func bestBodyText(p *gmail.MessagePart) string { return html } +func bestBodyHTML(p *gmail.MessagePart) string { + if p == nil { + return "" + } + html := findPartBody(p, "text/html") + if html != "" { + return html + } + plain := findPartBody(p, "text/plain") + return plain +} + func bestBodyForDisplay(p *gmail.MessagePart) (string, bool) { if p == nil { return "", false