From 011f033f4b6f91c1e67d1e6ddfa64dcdc57ef0d0 Mon Sep 17 00:00:00 2001 From: Jean-Michel Tremblay Date: Fri, 19 Jun 2026 09:04:11 -0400 Subject: [PATCH] Recent list: full first-name initials for hyphenated names Jean-Michel -> JM (every hyphen-separated part), Lynna -> L. Adds a shortWho test. Co-Authored-By: Claude Opus 4.8 --- internal/web/views.go | 18 ++++++++++++++---- internal/web/views_test.go | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/internal/web/views.go b/internal/web/views.go index 6c3d888..a4069f5 100644 --- a/internal/web/views.go +++ b/internal/web/views.go @@ -225,15 +225,25 @@ func (s *Server) handleAttachmentFile(w http.ResponseWriter, r *http.Request) { http.ServeContent(w, r, a.OriginalFilename, a.UploadedAt, bytes.NewReader(a.ImageData)) } -// shortWho abbreviates a "First Last" person label to "F. Last" to keep the recent -// list compact on narrow screens. Single-word or empty labels are left as-is. +// shortWho abbreviates a "First Last" person label to ". Last" to keep +// the recent list compact on narrow screens. The first name's initials include +// every hyphen-separated part ("Jean-Michel" -> "JM", "Lynna" -> "L"). Single-word +// or empty labels are left as-is. func shortWho(label string) string { fields := strings.Fields(label) if len(fields) < 2 { return label } - first := []rune(fields[0]) - return string(first[0]) + ". " + fields[len(fields)-1] + var initials strings.Builder + for _, part := range strings.Split(fields[0], "-") { + if part = strings.TrimSpace(part); part != "" { + initials.WriteString(strings.ToUpper(string([]rune(part)[0]))) + } + } + if initials.Len() == 0 { + return label + } + return initials.String() + ". " + fields[len(fields)-1] } // dollars formats integer cents as a plain dollar string, e.g. 1234 -> "12.34". diff --git a/internal/web/views_test.go b/internal/web/views_test.go index 767ed44..e417cfe 100644 --- a/internal/web/views_test.go +++ b/internal/web/views_test.go @@ -102,6 +102,21 @@ func TestRecentPage_ListsAndPages(t *testing.T) { } } +func TestShortWho(t *testing.T) { + cases := map[string]string{ + "Jean-Michel Tremblay": "JM. Tremblay", + "Lynna Nguyen": "L. Nguyen", + "Jude Tremblay": "J. Tremblay", + "Madonna": "Madonna", // single word unchanged + "": "", + } + for in, want := range cases { + if got := shortWho(in); got != want { + t.Errorf("shortWho(%q) = %q, want %q", in, got, want) + } + } +} + func TestReceiptFile_ServesBlob(t *testing.T) { s := testServerWithStore(t) addReceipt(t, s, "file1", 100, time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC))