aboutsummaryrefslogtreecommitdiff
path: root/cmds/rss.go
diff options
context:
space:
mode:
authorSam Scholten2026-08-30 20:40:39 +1000
committerSam Scholten2026-08-30 20:40:39 +1000
commit49d9f3e0eaeeab234c3ec903be43b88919d98eff (patch)
treed44472e50119dd8ef9ab406a65b0f6b16a4daf7a /cmds/rss.go
parenteff960c54620bfba47d40bc3792ba805dea3dab3 (diff)
downloadfluxrec-49d9f3e0eaeeab234c3ec903be43b88919d98eff.tar.gz
fluxrec-49d9f3e0eaeeab234c3ec903be43b88919d98eff.zip
rss: render score head as HTML paragraph
Descriptions render as sanitized HTML in readers, where bare newlines collapse and the feed/score line ran into the article text. Wrap the headline in <p><em> so it breaks cleanly and reads as metadata, escaped on the wire by encoding/xml as description-carried HTML should be.
Diffstat (limited to 'cmds/rss.go')
-rw-r--r--cmds/rss.go23
1 files changed, 15 insertions, 8 deletions
diff --git a/cmds/rss.go b/cmds/rss.go
index 8679f6f..30be578 100644
--- a/cmds/rss.go
+++ b/cmds/rss.go
@@ -49,8 +49,9 @@ type rssDocument struct {
// RSS 2.0 document. Each item title gets the source feed as a rune-capped
// suffix (readers show the channel title as the source of every item, so
// this is the only in-list provenance), and the description body opens
-// with feed + model score + the batch-wide median score. Item content was
-// already cleaned when the run row was written.
+// with feed + model score + the batch-wide median score as an emphasized
+// HTML paragraph (bare newlines collapse where descriptions render as
+// HTML). Item content was already cleaned when the run row was written.
func RenderRSS(runs []core.RunRow) ([]byte, error) {
doc := rssDocument{
Version: "2.0",
@@ -95,9 +96,14 @@ func truncateRunes(s string, max int) string {
return string([]rune(s)[:max]) + "…"
}
-// rssDescription builds the item body: first a headline line with the
-// source feed, model score, and batch-wide median (omitted for run rows
-// written before the median was logged), then the cleaned content (if any).
+// rssDescription builds the item body: first a headline with the source
+// feed, model score, and batch-wide median (omitted for run rows written
+// before the median was logged), then the cleaned content (if any). The
+// headline is wrapped in an emphasized HTML paragraph: descriptions render
+// as sanitized HTML in most readers, where bare newlines collapse and the
+// metadata line would run into the article text. encoding/xml escapes the
+// tags on the wire, which is exactly how description-carried HTML is meant
+// to be transported.
func rssDescription(k core.KeptItem, median *float64) string {
head := fmt.Sprintf("score %.2f", k.Score)
if median != nil {
@@ -106,8 +112,9 @@ func rssDescription(k core.KeptItem, median *float64) string {
if k.FeedTitle != "" {
head = k.FeedTitle + " · " + head
}
- if k.Content == "" {
- return head
+ body := "<p><em>" + head + "</em></p>"
+ if k.Content != "" {
+ body += "\n" + k.Content
}
- return head + "\n\n" + k.Content
+ return body
}