diff --git a/internal/reader/atom/atom_10.go b/internal/reader/atom/atom_10.go index caf08c24..afe87a68 100644 --- a/internal/reader/atom/atom_10.go +++ b/internal/reader/atom/atom_10.go @@ -39,6 +39,10 @@ type Atom10Feed struct { // atom:feed elements MUST contain exactly one atom:title element. Title Atom10Text `xml:"http://www.w3.org/2005/Atom title"` + // The "atom:subtitle" element is a Text construct that + // contains a human-readable description or subtitle for the feed. + Subtitle Atom10Text `xml:"http://www.w3.org/2005/Atom subtitle"` + // The "atom:author" element is a Person construct that indicates the // author of the entry or feed. // diff --git a/internal/reader/atom/atom_10_adapter.go b/internal/reader/atom/atom_10_adapter.go index a0a73623..ce80e814 100644 --- a/internal/reader/atom/atom_10_adapter.go +++ b/internal/reader/atom/atom_10_adapter.go @@ -55,6 +55,9 @@ func (a *Atom10Adapter) BuildFeed(baseURL string) *model.Feed { feed.Title = feed.SiteURL } + // Populate the feed description. + feed.Description = a.atomFeed.Subtitle.Body() + // Populate the feed icon. if a.atomFeed.Icon != "" { if absoluteIconURL, err := urllib.AbsoluteURL(feed.SiteURL, a.atomFeed.Icon); err == nil { diff --git a/internal/reader/atom/atom_10_test.go b/internal/reader/atom/atom_10_test.go index f3599476..6c664faf 100644 --- a/internal/reader/atom/atom_10_test.go +++ b/internal/reader/atom/atom_10_test.go @@ -82,6 +82,29 @@ func TestParseAtomSample(t *testing.T) { } } +func TestParseFeedWithSubtitle(t *testing.T) { + data := ` + + Example Feed + This is a subtitle + + 2003-12-13T18:30:02Z + + John Doe + + urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 + ` + + feed, err := Parse("http://example.org/feed.xml", bytes.NewReader([]byte(data)), "10") + if err != nil { + t.Fatal(err) + } + + if feed.Description != "This is a subtitle" { + t.Errorf("Incorrect description, got: %s", feed.Description) + } +} + func TestParseFeedWithoutTitle(t *testing.T) { data := ` diff --git a/internal/reader/json/adapter.go b/internal/reader/json/adapter.go index cf54100f..89aa93ea 100644 --- a/internal/reader/json/adapter.go +++ b/internal/reader/json/adapter.go @@ -26,9 +26,10 @@ func NewJSONAdapter(jsonFeed *JSONFeed) *JSONAdapter { func (j *JSONAdapter) BuildFeed(baseURL string) *model.Feed { feed := &model.Feed{ - Title: strings.TrimSpace(j.jsonFeed.Title), - FeedURL: strings.TrimSpace(j.jsonFeed.FeedURL), - SiteURL: strings.TrimSpace(j.jsonFeed.HomePageURL), + Title: strings.TrimSpace(j.jsonFeed.Title), + FeedURL: strings.TrimSpace(j.jsonFeed.FeedURL), + SiteURL: strings.TrimSpace(j.jsonFeed.HomePageURL), + Description: strings.TrimSpace(j.jsonFeed.Description), } if feed.FeedURL == "" { diff --git a/internal/reader/json/parser_test.go b/internal/reader/json/parser_test.go index 6f62831f..6e2038b3 100644 --- a/internal/reader/json/parser_test.go +++ b/internal/reader/json/parser_test.go @@ -41,6 +41,10 @@ func TestParseJsonFeedVersion1(t *testing.T) { t.Errorf("Incorrect title, got: %s", feed.Title) } + if feed.Description != "" { + t.Errorf("Incorrect description, got: %s", feed.Description) + } + if feed.FeedURL != "https://example.org/feed.json" { t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL) } @@ -90,6 +94,26 @@ func TestParseJsonFeedVersion1(t *testing.T) { } } +func TestParseFeedWithDescription(t *testing.T) { + data := `{ + "version": "https://jsonfeed.org/version/1", + "title": "My Example Feed", + "description": "This is a sample feed description.", + "home_page_url": "https://example.org/", + "feed_url": "https://example.org/feed.json", + "items": [] + }` + + feed, err := Parse("https://example.org/feed.json", bytes.NewBufferString(data)) + if err != nil { + t.Fatal(err) + } + + if feed.Description != "This is a sample feed description." { + t.Errorf("Incorrect description, got: %s", feed.Description) + } +} + func TestParsePodcast(t *testing.T) { data := `{ "version": "https://jsonfeed.org/version/1", diff --git a/internal/reader/rdf/adapter.go b/internal/reader/rdf/adapter.go index f90ebaca..13d8f06f 100644 --- a/internal/reader/rdf/adapter.go +++ b/internal/reader/rdf/adapter.go @@ -26,9 +26,10 @@ func NewRDFAdapter(rdf *RDF) *RDFAdapter { func (r *RDFAdapter) BuildFeed(baseURL string) *model.Feed { feed := &model.Feed{ - Title: stripTags(r.rdf.Channel.Title), - FeedURL: strings.TrimSpace(baseURL), - SiteURL: strings.TrimSpace(r.rdf.Channel.Link), + Title: stripTags(r.rdf.Channel.Title), + FeedURL: strings.TrimSpace(baseURL), + SiteURL: strings.TrimSpace(r.rdf.Channel.Link), + Description: strings.TrimSpace(r.rdf.Channel.Description), } if feed.Title == "" { diff --git a/internal/reader/rdf/parser_test.go b/internal/reader/rdf/parser_test.go index 021772b4..7f99a952 100644 --- a/internal/reader/rdf/parser_test.go +++ b/internal/reader/rdf/parser_test.go @@ -23,8 +23,7 @@ func TestParseRDFSample(t *testing.T) { XML.com http://xml.com/pub - XML.com features a rich mix of information and services - for the XML community. + XML.com features a rich mix of information and services for the XML community. @@ -84,6 +83,10 @@ func TestParseRDFSample(t *testing.T) { t.Errorf("Incorrect title, got: %s", feed.Title) } + if feed.Description != "XML.com features a rich mix of information and services for the XML community." { + t.Errorf("Incorrect description, got: %s", feed.Description) + } + if feed.FeedURL != "http://xml.com/pub/rdf.xml" { t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL) } diff --git a/internal/reader/rss/adapter.go b/internal/reader/rss/adapter.go index deadeee9..36b39da4 100644 --- a/internal/reader/rss/adapter.go +++ b/internal/reader/rss/adapter.go @@ -28,9 +28,10 @@ func NewRSSAdapter(rss *RSS) *RSSAdapter { func (r *RSSAdapter) BuildFeed(baseURL string) *model.Feed { feed := &model.Feed{ - Title: html.UnescapeString(strings.TrimSpace(r.rss.Channel.Title)), - FeedURL: strings.TrimSpace(baseURL), - SiteURL: strings.TrimSpace(r.rss.Channel.Link), + Title: html.UnescapeString(strings.TrimSpace(r.rss.Channel.Title)), + FeedURL: strings.TrimSpace(baseURL), + SiteURL: strings.TrimSpace(r.rss.Channel.Link), + Description: strings.TrimSpace(r.rss.Channel.Description), } // Ensure the Site URL is absolute. diff --git a/internal/reader/rss/parser_test.go b/internal/reader/rss/parser_test.go index 7bee9b29..efce4575 100644 --- a/internal/reader/rss/parser_test.go +++ b/internal/reader/rss/parser_test.go @@ -67,6 +67,10 @@ func TestParseRss2Sample(t *testing.T) { t.Errorf("Incorrect title, got: %s", feed.Title) } + if feed.Description != "Liftoff to Space Exploration." { + t.Errorf("Incorrect description, got: %s", feed.Description) + } + if feed.FeedURL != "http://liftoff.msfc.nasa.gov/rss.xml" { t.Errorf("Incorrect feed URL, got: %s", feed.FeedURL) } @@ -237,6 +241,14 @@ func TestParseEntryWithoutTitleAndDescription(t *testing.T) { t.Fatal(err) } + if feed.Description != "" { + t.Errorf("Expected empty feed description, got: %s", feed.Description) + } + + if len(feed.Entries) != 1 { + t.Errorf("Expected 1 entry, got: %d", len(feed.Entries)) + } + if feed.Entries[0].Title != "https://example.org/item" { t.Errorf("Incorrect entry title, got: %s", feed.Entries[0].Title) }