diff --git a/internal/render/golden_test.go b/internal/render/golden_test.go index 34d3089..f1ebec5 100644 --- a/internal/render/golden_test.go +++ b/internal/render/golden_test.go @@ -62,10 +62,17 @@ func goldenCases() map[string]func(io.Writer) { ReplyCount: 4, RepostCount: 5, LikeCount: 6, QuoteCount: 7, } + external := simple("How it's going", "e1") + external.Embed = &bsky.Embed{ + Type: "app.bsky.embed.external#view", + External: &bsky.ExternalView{URI: "https://atproto.com/", Title: "Welcome to atproto", Description: "ignored in summaries"}, + } + items := []ListItem{ {Post: simple("a repost", "r1"), RepostBy: "reposter.bsky.social"}, {Post: simple("a reply", "r2"), Reply: true}, {Post: rich}, + {Post: external}, } pub := &bsky.Publication{ diff --git a/internal/render/render.go b/internal/render/render.go index 9d8623e..f97f0e7 100644 --- a/internal/render/render.go +++ b/internal/render/render.go @@ -171,6 +171,7 @@ func writeSummary(w io.Writer, it ListItem) { fmt.Fprintln(w, oneParagraph(text, 280)) } writeSummaryImages(w, post) + writeSummaryExternal(w, post.Embed) if att := attachmentSummary(post.Embed); att != "" { fmt.Fprintf(w, "%s\n", att) } @@ -192,6 +193,20 @@ func writeSummaryImages(w io.Writer, post *bsky.PostView) { } } +// writeSummaryExternal links a list summary's external/link-card embed straight +// to its target, with the card's title (or the URL) as the label. +func writeSummaryExternal(w io.Writer, e *bsky.Embed) { + ext := e.MediaExternal() + if ext == nil || ext.URI == "" { + return + } + title := strings.TrimSpace(ext.Title) + if title == "" { + title = ext.URI + } + fmt.Fprintf(w, "=> %s 🔗 %s\n", ext.URI, oneLine(title)) +} + // linkLabel picks the label for a post link: the post's own anchor text when it // added a custom label, or a generic note when the text is just the URL. func linkLabel(l bsky.Link) string { @@ -282,11 +297,8 @@ func attachmentSummary(e *bsky.Embed) string { return "" } var parts []string - // Images are surfaced as their own links in summaries, so they aren't - // repeated here. - if e.MediaExternal() != nil { - parts = append(parts, "link card") - } + // Images and link cards are surfaced as their own links in summaries, so + // they aren't repeated here. if e.Type == "app.bsky.embed.video#view" { parts = append(parts, "video") } diff --git a/internal/render/testdata/golden/list.gmi b/internal/render/testdata/golden/list.gmi index 07cd8c4..13376d6 100644 --- a/internal/render/testdata/golden/list.gmi +++ b/internal/render/testdata/golden/list.gmi @@ -16,4 +16,9 @@ see foo [quoted post] 4 replies · 5 reposts · 6 likes +=> /p/byjp.me/p/e1/ 2026-05-30 JP +How it's going +=> https://atproto.com/ 🔗 Welcome to atproto +1 replies · 2 reposts · 3 likes + => /p/byjp.me/posts/?cursor=cursor123 More →