From 6daf4a241d08b7a76be64e60fdb4a6e64ec2fb2c Mon Sep 17 00:00:00 2001 From: Gwen Malmquist Date: Tue, 3 Mar 2026 20:37:03 +0000 Subject: [PATCH] Replace `Category string` with `Categories []string` Both RSS and Atom support multiple categories on feeds and entries, per their respective specifications. This branch supports that, and additionally plumbs the categories field through to both RSS and Atom variants. This addresses issue #77, which has as of writing been closed as stale without actually being fixed. *This change is breaking.* --- atom.go | 4 +-- consume_test.go | 75 +++++++++++++++++++++++++------------------------ feed.go | 2 ++ rss.go | 10 ++++--- test.rss | 4 +++ 5 files changed, 53 insertions(+), 42 deletions(-) diff --git a/atom.go b/atom.go index 73de995..a13b83e 100644 --- a/atom.go +++ b/atom.go @@ -45,7 +45,7 @@ type AtomEntry struct { Title string `xml:"title"` // required Updated string `xml:"updated"` // required Id string `xml:"id"` // required - Category string `xml:"category,omitempty"` + Categories []string `xml:"category,omitempty"` Content *AtomContent Rights string `xml:"rights,omitempty"` Source string `xml:"source,omitempty"` @@ -72,7 +72,7 @@ type AtomFeed struct { Title string `xml:"title"` // required Id string `xml:"id"` // required Updated string `xml:"updated"` // required - Category string `xml:"category,omitempty"` + Categories []string `xml:"category,omitempty"` Icon string `xml:"icon,omitempty"` Logo string `xml:"logo,omitempty"` Rights string `xml:"rights,omitempty"` // copyright used diff --git a/consume_test.go b/consume_test.go index 5abe4d1..687a0c5 100644 --- a/consume_test.go +++ b/consume_test.go @@ -25,7 +25,7 @@ var testRssFeedXML = RssFeedXml{ WebMaster: "", PubDate: "Tue, 30 Oct 2018 23:22:00 GMT", LastBuildDate: "Tue, 30 Oct 2018 23:22:37 GMT", - Category: "", + Categories: []string{"you say goodbye", "i say hello"}, Generator: "RSS for Node", Docs: "", Cloud: "", @@ -43,7 +43,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Exercitation ut Lorem sint proident.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941720", IsPermaLink: "true"}, @@ -57,12 +57,15 @@ var testRssFeedXML = RssFeedXml{ Description: "Ea est do quis fugiat exercitation.", Content: (*RssContent)(nil), Author: "", - Category: "", - Comments: "", - Enclosure: (*RssEnclosure)(nil), - Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941660", IsPermaLink: "true"}, - PubDate: "Tue, 30 Oct 2018 23:21:00 GMT", - Source: "", + Categories: []string{ + "i don't know why you say goodbye", + "i say hello, hello, hello-o-o", + }, + Comments: "", + Enclosure: (*RssEnclosure)(nil), + Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941660", IsPermaLink: "true"}, + PubDate: "Tue, 30 Oct 2018 23:21:00 GMT", + Source: "", }, { XMLName: xml.Name{Space: "", Local: "item"}, @@ -71,7 +74,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Ipsum velit cillum ad laborum sit nulla exercitation consequat sint veniam culpa veniam voluptate incididunt.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941600", IsPermaLink: "true"}, @@ -85,7 +88,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Ullamco pariatur aliqua consequat ea veniam id qui incididunt laborum.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941540", IsPermaLink: "true"}, @@ -99,7 +102,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Velit proident aliquip aliquip anim mollit voluptate laboris voluptate et occaecat occaecat laboris ea nulla.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941480", IsPermaLink: "true"}, @@ -113,7 +116,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Do in quis mollit consequat id in minim laborum sint exercitation laborum elit officia.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941420", IsPermaLink: "true"}, @@ -127,7 +130,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Irure id sint ullamco Lorem magna consectetur officia adipisicing duis incididunt.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941360", IsPermaLink: "true"}, @@ -141,7 +144,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Sunt anim excepteur esse nisi commodo culpa laborum exercitation ad anim ex elit.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941300", IsPermaLink: "true"}, @@ -155,7 +158,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Excepteur aliquip fugiat ex labore nisi.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941240", IsPermaLink: "true"}, @@ -169,7 +172,7 @@ var testRssFeedXML = RssFeedXml{ Description: "Id proident adipisicing proident pariatur aute pariatur pariatur dolor dolor in voluptate dolor.", Content: (*RssContent)(nil), Author: "", - Category: "", + Categories: nil, Comments: "", Enclosure: (*RssEnclosure)(nil), Guid: &RssGuid{XMLName: xml.Name{Local: "guid"}, Id: "http://example.com/test/1540941180", IsPermaLink: "true"}, @@ -181,16 +184,16 @@ var testRssFeedXML = RssFeedXml{ } var testAtomFeedXML = AtomFeed{ - XMLName: xml.Name{Space: "", Local: "feed"}, - Xmlns: "", - Title: "Lorem ipsum feed for an interval of 1 minutes", - Id: "", - Updated: "", - Category: "", - Icon: "", - Logo: "", - Rights: "", - Subtitle: "", + XMLName: xml.Name{Space: "", Local: "feed"}, + Xmlns: "", + Title: "Lorem ipsum feed for an interval of 1 minutes", + Id: "", + Updated: "", + Categories: nil, + Icon: "", + Logo: "", + Rights: "", + Subtitle: "", Link: &AtomLink{ XMLName: xml.Name{Space: "", Local: "link"}, Href: "", @@ -210,7 +213,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:22:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -226,7 +229,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:21:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -242,7 +245,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:20:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -258,7 +261,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:19:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -274,7 +277,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:18:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -290,7 +293,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:17:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -306,7 +309,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:16:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -322,7 +325,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:15:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -338,7 +341,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:14:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", @@ -354,7 +357,7 @@ var testAtomFeedXML = AtomFeed{ Title: "Lorem ipsum 2018-10-30T23:13:00+00:00", Updated: "", Id: "", - Category: "", + Categories: nil, Content: (*AtomContent)(nil), Rights: "", Source: "", diff --git a/feed.go b/feed.go index 929c226..42d4476 100644 --- a/feed.go +++ b/feed.go @@ -33,6 +33,7 @@ type Item struct { Description string // used as description in rss, summary in atom Id string // used as guid in rss, id in atom IsPermaLink string // an optional parameter for guid in rss + Categories []string Updated time.Time Created time.Time Enclosure *Enclosure @@ -51,6 +52,7 @@ type Feed struct { Items []*Item Copyright string Image *Image + Categories []string } // add a new Item to a Feed diff --git a/rss.go b/rss.go index 9326cef..1424107 100644 --- a/rss.go +++ b/rss.go @@ -51,7 +51,7 @@ type RssFeed struct { WebMaster string `xml:"webMaster,omitempty"` PubDate string `xml:"pubDate,omitempty"` // created or updated LastBuildDate string `xml:"lastBuildDate,omitempty"` // updated used - Category string `xml:"category,omitempty"` + Categories []string `xml:"category,omitempty"` Generator string `xml:"generator,omitempty"` Docs string `xml:"docs,omitempty"` Cloud string `xml:"cloud,omitempty"` @@ -70,9 +70,9 @@ type RssItem struct { Link string `xml:"link"` // required Description string `xml:"description"` // required Content *RssContent - Author string `xml:"author,omitempty"` - Category string `xml:"category,omitempty"` - Comments string `xml:"comments,omitempty"` + Author string `xml:"author,omitempty"` + Categories []string `xml:"category,omitempty"` + Comments string `xml:"comments,omitempty"` Enclosure *RssEnclosure Guid *RssGuid // Id used PubDate string `xml:"pubDate,omitempty"` // created or updated @@ -104,6 +104,7 @@ func newRssItem(i *Item) *RssItem { Title: i.Title, Description: i.Description, PubDate: anyTimeFormat(time.RFC1123Z, i.Created, i.Updated), + Categories: i.Categories, } if i.Id != "" { item.Guid = &RssGuid{Id: i.Id, IsPermaLink: i.IsPermaLink} @@ -159,6 +160,7 @@ func (r *Rss) RssFeed() *RssFeed { LastBuildDate: build, Copyright: r.Copyright, Image: image, + Categories: r.Categories, } for _, i := range r.Items { channel.Items = append(channel.Items, newRssItem(i)) diff --git a/test.rss b/test.rss index 8d912ab..a5f312f 100644 --- a/test.rss +++ b/test.rss @@ -12,6 +12,8 @@ Tue, 30 Oct 2018 23:22:00 GMT 60 + you say goodbye + i say hello <![CDATA[Lorem ipsum 2018-10-30T23:22:00+00:00]]> @@ -27,6 +29,8 @@ http://example.com/test/1540941660 Tue, 30 Oct 2018 23:21:00 GMT + i don't know why you say goodbye + i say hello, hello, hello-o-o <![CDATA[Lorem ipsum 2018-10-30T23:20:00+00:00]]>