From 4220a2acc61275bc57e10057954467272683f031 Mon Sep 17 00:00:00 2001 From: Jason Streifling Date: Wed, 16 Oct 2024 19:59:28 +0200 Subject: [PATCH] Added and corrected comments --- atom.go | 13 +++++++++++-- category.go | 4 ++++ commonAttributes.go | 2 ++ content.go | 1 + date.go | 5 +++++ entry.go | 22 +++++++++++++++------- extensionAttribute.go | 2 ++ extensionElement.go | 4 ++++ feed.go | 39 ++++++++++----------------------------- generator.go | 3 +++ icon.go | 3 +++ id.go | 2 ++ inlineOtherContent.go | 9 +++++++++ inlineTextContent.go | 9 +++++++++ inlineXHTMLContent.go | 9 +++++++++ link.go | 17 +++++++++++++++++ logo.go | 3 +++ outOfLineContent.go | 9 +++++++++ person.go | 5 ++++- plainText.go | 3 +++ source.go | 2 ++ text.go | 1 + xhtmlText.go | 3 +++ 23 files changed, 131 insertions(+), 39 deletions(-) diff --git a/atom.go b/atom.go index c4a1bca..0a11cb1 100644 --- a/atom.go +++ b/atom.go @@ -31,14 +31,16 @@ type ( // return isValidURL(uri) || isValidURN(uri) // } -// isValidIRI checks whether an IRI is valid or not. +// isValidIRI checks whether an IRI is valid or not. It returns a bool. // The used pattern stems from -// https://www.w3.org/2011/04/XMLSchema/TypeLibrary-IRI-RFC3987.xsd +// https://www.w3.org/2011/04/XMLSchema/TypeLibrary-IRI-RFC3987.xsd. func isValidIRI(iri IRI) bool { pattern := `((([A-Za-z])[A-Za-z0-9+\-\.]*):((//(((([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽!$&'()*+,;=:]|(%[0-9A-Fa-f][0-9A-Fa-f]))*@))?((\[((((([0-9A-Fa-f]{0,4}:)){6}(([0-9A-Fa-f]{0,4}:[0-9A-Fa-f]{0,4})|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))))|(::(([0-9A-Fa-f]{0,4}:)){5}(([0-9A-Fa-f]{0,4}:[0-9A-Fa-f]{0,4})|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))))|(([0-9A-Fa-f]{0,4})?::(([0-9A-Fa-f]{0,4}:)){4}(([0-9A-Fa-f]{0,4}:[0-9A-Fa-f]{0,4})|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))))|((((([0-9A-Fa-f]{0,4}:))?[0-9A-Fa-f]{0,4}))?::(([0-9A-Fa-f]{0,4}:)){3}(([0-9A-Fa-f]{0,4}:[0-9A-Fa-f]{0,4})|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))))|((((([0-9A-Fa-f]{0,4}:)){0,2}[0-9A-Fa-f]{0,4}))?::(([0-9A-Fa-f]{0,4}:)){2}(([0-9A-Fa-f]{0,4}:[0-9A-Fa-f]{0,4})|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))))|((((([0-9A-Fa-f]{0,4}:)){0,3}[0-9A-Fa-f]{0,4}))?::[0-9A-Fa-f]{0,4}:(([0-9A-Fa-f]{0,4}:[0-9A-Fa-f]{0,4})|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))))|((((([0-9A-Fa-f]{0,4}:)){0,4}[0-9A-Fa-f]{0,4}))?::(([0-9A-Fa-f]{0,4}:[0-9A-Fa-f]{0,4})|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))))|((((([0-9A-Fa-f]{0,4}:)){0,5}[0-9A-Fa-f]{0,4}))?::[0-9A-Fa-f]{0,4})|((((([0-9A-Fa-f]{0,4}:)){0,6}[0-9A-Fa-f]{0,4}))?::))|(v[0-9A-Fa-f]+\.[A-Za-z0-9\-\._~!$&'()*+,;=:]+))\])|(([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5]))\.([0-9]|([1-9][0-9])|(1([0-9]){2})|(2[0-4][0-9])|(25[0-5])))|(([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=]))*)((:[0-9]*))?)((/(([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=:@]))*))*)|(/(((([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=:@]))+((/(([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=:@]))*))*))?)|((([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=:@]))+((/(([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=:@]))*))*)|)((\?(([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=:@])|[-󰀀-󿿽􀀀-􏿽/?])*))?((#((([A-Za-z0-9\-\._~ -퟿豈-﷏ﷰ-￯𐀀-🿽𠀀-𯿽𰀀-𿿽񀀀-񏿽񐀀-񟿽񠀀-񯿽񰀀-񿿽򀀀-򏿽򐀀-򟿽򠀀-򯿽򰀀-򿿽󀀀-󏿽󐀀-󟿽󡀀-󯿽]|(%[0-9A-Fa-f][0-9A-Fa-f])|[!$&'()*+,;=:@])|/|\?))*))?)` return regexp.MustCompile(pattern).MatchString(string(iri)) } +// isCorrectlyEscaped checks whether a string is correctly escaped as per +// RFC4287. It returns a bool. func isCorrectlyEscaped(text string) bool { relevantEntities := []string{"&", "<", ">", """, "'"} @@ -51,6 +53,8 @@ func isCorrectlyEscaped(text string) bool { return true } +// isCompositeMediaType checks whether a string is a composite media type. It +// returns a bool. func isCompositeMediaType(mediaType string) bool { mediaType, _, err := mime.ParseMediaType(mediaType) if err != nil { @@ -60,6 +64,8 @@ func isCompositeMediaType(mediaType string) bool { return strings.HasPrefix(mediaType, "multipart/") || strings.HasPrefix(mediaType, "message/") } +// isXMLMediaType checks whether a string is an xml media type. It returns a +// bool. func isXMLMediaType(mediaType string) bool { mediaType, _, err := mime.ParseMediaType(mediaType) if err != nil { @@ -69,11 +75,14 @@ func isXMLMediaType(mediaType string) bool { return strings.HasSuffix(mediaType, "/xml") || strings.HasSuffix(mediaType, "+xml") } +// isValidMediaType checks whether a string is a valid media type. It returns a +// bool. func isValidMediaType(mediaType string) bool { _, _, err := mime.ParseMediaType(mediaType) return err == nil } +// isValidLanguageTag checks whether a LanguageTag is valid. It returns a bool. func isValidLanguageTag(tag LanguageTag) bool { _, err := language.Parse(string(tag)) return err == nil diff --git a/category.go b/category.go index e4ad587..19febe6 100644 --- a/category.go +++ b/category.go @@ -14,6 +14,7 @@ type Category struct { Label string `xml:"label,attr,omitempty"` } +// NewCategory creates a new Category. It returns a *Category and an error. func NewCategory(term string) (*Category, error) { content, err := NewContent(InlineText, "", "") if err != nil { @@ -23,10 +24,13 @@ func NewCategory(term string) (*Category, error) { return &Category{Term: term, Content: content}, nil } +// SetLabel sets the label of the Category. func (c *Category) SetLabel(label string) { c.Label = html.UnescapeString(label) } +// Check checks the Category for incompatibilities with RFC4287. It returns an +// error. func (c *Category) Check() error { if c.Term == "" { return errors.New("term attribute of category empty") diff --git a/commonAttributes.go b/commonAttributes.go index 696e512..faed9e5 100644 --- a/commonAttributes.go +++ b/commonAttributes.go @@ -8,6 +8,8 @@ type CommonAttributes struct { UndefinedAttributes []*ExtensionAttribute `xml:",any"` } +// Check checks the CommonAttributes for incompatibilities with RFC4287. It +// returns an error. func (c *CommonAttributes) Check() error { for i, e := range c.UndefinedAttributes { if err := e.Check(); err != nil { diff --git a/content.go b/content.go index e8112f9..3ad8537 100644 --- a/content.go +++ b/content.go @@ -18,6 +18,7 @@ type Content interface { Check() error } +// NewContent creates a new Content. It returns a Content and an error. func NewContent(contentType int, mediaType string, content any) (Content, error) { switch contentType { case 0: diff --git a/date.go b/date.go index 008fb3e..fbe2d86 100644 --- a/date.go +++ b/date.go @@ -10,14 +10,19 @@ type Date struct { DateTime string } +// DateTime formats a time.Time to string formated as defined by RFC3339. It +// returns a string. func DateTime(t time.Time) string { return string(t.Format(time.RFC3339)) } +// NewDate creates a new Date. It returns a *Date. func NewDate(t time.Time) *Date { return &Date{DateTime: DateTime(t)} } +// Check checks the Date for incompatibilities with RFC4287. It returns an +// error. func (d *Date) Check() error { if d.DateTime == "" { return errors.New("date time element of date is empty") diff --git a/entry.go b/entry.go index 201401b..efdc34b 100644 --- a/entry.go +++ b/entry.go @@ -28,6 +28,8 @@ type Entry struct { Extensions []*ExtensionElement `xml:",any,omitempty"` } +// checkAuthors checks the entry's authors for incompatibilities with RFC4287. +// It returns an errors. // atom:entry elements MUST contain one or more atom:author elements, unless // the atom:entry contains an atom:source element that contains an atom:author // element or, in an Atom Feed Document, the atom:feed element contains an @@ -48,17 +50,21 @@ func (e *Entry) checkAuthors() error { return nil } -func alternateRelExists(l []*Link) bool { - for _, link := range l { - if link.Rel == "alternate" { - return true - } +// NewEntry creates a new Entry. It returns a *Entry and an error. +func NewEntry(title string) (*Entry, error) { + text, err := NewText("text", title) + if err != nil { + return nil, fmt.Errorf("error creating new entry: %v", err) } - return false + return &Entry{ + ID: NewID(), + Title: text, + Updated: NewDate(time.Now()), + }, nil } -// AddExtension adds the extension to the entry +// AddExtension adds the ExtensionElement to the Entry. func (e *Entry) AddExtension(x *ExtensionElement) { if e.Extensions == nil { e.Extensions = make([]*ExtensionElement, 1) @@ -70,6 +76,8 @@ func (e *Entry) AddExtension(x *ExtensionElement) { e.Updated.DateTime = DateTime(time.Now()) } +// Check checks the Entry for incompatibilities with RFC4287. It returns an +// error. func (e *Entry) Check() error { if e.ID == nil { return errors.New("no id element of entry") diff --git a/extensionAttribute.go b/extensionAttribute.go index 736ca3e..afdedd4 100644 --- a/extensionAttribute.go +++ b/extensionAttribute.go @@ -10,6 +10,8 @@ type ExtensionAttribute struct { XMLName xml.Name } +// Check checks the ExtensionAttribute for incompatibilities with RFC4287. It +// returns an error. func (e *ExtensionAttribute) Check() error { if e.Value == nil { return errors.New("value element of extension attribute empty") diff --git a/extensionElement.go b/extensionElement.go index de17c5d..4e0a859 100644 --- a/extensionElement.go +++ b/extensionElement.go @@ -10,10 +10,14 @@ type ExtensionElement struct { XMLName xml.Name } +// NewExtensionElement creates a new ExtensionElement. It returns a +// *ExtensionElement. func NewExtensionElement(name string, value any) *ExtensionElement { return &ExtensionElement{XMLName: xml.Name{Local: name}, Value: value} } +// Check checks the ExtensionElement for incompatibilities with RFC4287. It +// returns an error. func (e *ExtensionElement) Check() error { if e.Value == nil { return errors.New("value element of extension element empty") diff --git a/feed.go b/feed.go index 0b49775..ee08c65 100644 --- a/feed.go +++ b/feed.go @@ -26,7 +26,7 @@ type Feed struct { Entries []*Entry `xml:"entry,omitempty"` } -// NewFeed creates a new feed. +// NewFeed creates a new Feed. It returns a *Feed and an error. func NewFeed(title string) (*Feed, error) { text, err := NewText("text", title) if err != nil { @@ -40,7 +40,7 @@ func NewFeed(title string) (*Feed, error) { }, nil } -// AddAuthor adds the person as an author to the feed. +// AddAuthor adds the Person as an author to the Feed. func (f *Feed) AddAuthor(p *Person) { if f.Authors == nil { f.Authors = make([]*Person, 1) @@ -52,7 +52,7 @@ func (f *Feed) AddAuthor(p *Person) { f.Updated.DateTime = DateTime(time.Now()) } -// AddCategory adds the category to the feed. +// AddCategory adds the Category to the Feed. func (f *Feed) AddCategory(c *Category) { if f.Categories == nil { f.Categories = make([]*Category, 1) @@ -64,7 +64,7 @@ func (f *Feed) AddCategory(c *Category) { f.Updated.DateTime = DateTime(time.Now()) } -// AddContributor adds the contributor to the feed. +// AddContributor adds the Person as a contributor to the Feed. func (f *Feed) AddContributor(c *Person) { if f.Contributors == nil { f.Contributors = make([]*Person, 1) @@ -76,8 +76,7 @@ func (f *Feed) AddContributor(c *Person) { f.Updated.DateTime = DateTime(time.Now()) } -// AddLink adds the link to the feed. -// There should be one link with rel "self". +// AddLink adds the Link to the Feed. There should be one Link with Rel "self". func (f *Feed) AddLink(l *Link) { if f.Links == nil { f.Links = make([]*Link, 1) @@ -89,7 +88,7 @@ func (f *Feed) AddLink(l *Link) { f.Updated.DateTime = DateTime(time.Now()) } -// AddExtension adds the extension to the feed. +// AddExtension adds the Extension to the Feed. func (f *Feed) AddExtension(e *ExtensionElement) { if f.Extensions == nil { f.Extensions = make([]*ExtensionElement, 1) @@ -101,7 +100,7 @@ func (f *Feed) AddExtension(e *ExtensionElement) { f.Updated.DateTime = DateTime(time.Now()) } -// AddEntry adds the entry to the feed. +// AddEntry adds the Entry to the Feed. func (f *Feed) AddEntry(e *Entry) { if f.Entries == nil { f.Entries = make([]*Entry, 1) @@ -113,7 +112,8 @@ func (f *Feed) AddEntry(e *Entry) { f.Updated.DateTime = DateTime(time.Now()) } -// Check checks the feed for incompatibilities with RFC4287. +// Check checks the Feed for incompatibilities with RFC4287. It returns an +// error. func (f *Feed) Check() error { if f.ID == nil { return errors.New("no id element of feed") @@ -222,26 +222,7 @@ func (f *Feed) Check() error { return nil } -// TODO: Create complete link or delete -func (f *Feed) Standardize() { - if f.Links == nil { - f.Links = make([]*Link, 1) - f.Links[0] = &Link{Rel: "self"} - } else { - selfExists := false - for _, l := range f.Links { - if l.Rel == "self" { - selfExists = true - break - } - } - if !selfExists { - f.Links = append(f.Links, &Link{Rel: "self"}) - } - } -} - -// ToXML converts the feed to XML. +// ToXML converts the Feed to XML. It returns a string and an error. func (f *Feed) ToXML(encoding string) (string, error) { xml, err := xml.MarshalIndent(f, "", " ") if err != nil { diff --git a/generator.go b/generator.go index 9c27841..1090c43 100644 --- a/generator.go +++ b/generator.go @@ -13,10 +13,13 @@ type Generator struct { Text string `xml:"text"` } +// NewGenerator creates a new Generator. It returns a *Generator. func NewGenerator(text string) *Generator { return &Generator{Text: html.UnescapeString(text)} } +// Check checks the Generator for incompatibilities with RFC4287. It returns an +// error. func (g *Generator) Check() error { if g.URI != "" { if !isValidIRI(g.URI) { diff --git a/icon.go b/icon.go index e444b46..5ced9d5 100644 --- a/icon.go +++ b/icon.go @@ -10,10 +10,13 @@ type Icon struct { URI IRI `xml:"uri"` } +// NewIcon creates a new Icon. It returns a *Icon. func NewIcon(uri string) *Icon { return &Icon{URI: IRI(uri)} } +// Check checks the Icon for incompatibilities with RFC4287. It returns an +// error. func (i *Icon) Check() error { if i.URI == "" { return errors.New("uri element of icon empty") diff --git a/id.go b/id.go index 64a996b..96bf7fd 100644 --- a/id.go +++ b/id.go @@ -12,10 +12,12 @@ type ID struct { URI IRI `xml:"uri"` } +// NewID creates a new ID. It returns a *ID. func NewID() *ID { return &ID{URI: IRI(fmt.Sprint("urn:uuid:", uuid.New()))} } +// Check checks the ID for incompatibilities with RFC4287. It returns an error. func (i *ID) Check() error { if i.URI == "" { return errors.New("uri element of id empty") diff --git a/inlineOtherContent.go b/inlineOtherContent.go index c381e08..9b05ead 100644 --- a/inlineOtherContent.go +++ b/inlineOtherContent.go @@ -12,6 +12,8 @@ type InlineOtherContent struct { Type MediaType `xml:"type,attr,omitempty"` } +// newInlineOtherContent creates a new InlineOtherContent. It returns a +// *InlineOtherContent and an error. func newInlineOtherContent(mediaType string, content any) (*InlineOtherContent, error) { if mediaType, _, err := mime.ParseMediaType(mediaType); err != nil { return nil, fmt.Errorf("media type %v incompatible with inline other content", mediaType) @@ -20,12 +22,19 @@ func newInlineOtherContent(mediaType string, content any) (*InlineOtherContent, return &InlineOtherContent{Type: MediaType(mediaType), AnyElement: content}, nil } +// isContent checks whether the InlineOtherContent is a Content. It returns a +// bool. func (i *InlineOtherContent) isContent() bool { return true } +// hasSRC checks whether the InlineOtherContent has a SRC attribute. It returns +// a bool. func (i *InlineOtherContent) hasSRC() bool { return false } +// getType returns the Type of the InlineOtherContent as a string. func (i *InlineOtherContent) getType() string { return string(i.Type) } +// Check checks the InlineOtherContent for incompatibilities with RFC4287. It +// returns an error. func (i *InlineOtherContent) Check() error { mediaType := i.getType() diff --git a/inlineTextContent.go b/inlineTextContent.go index 69b0d18..4905c2d 100644 --- a/inlineTextContent.go +++ b/inlineTextContent.go @@ -12,6 +12,8 @@ type InlineTextContent struct { Texts []string `xml:"texts,omitempty"` } +// newInlineTextContent creates a new InlineTextContent. It returns a +// *InlineTextContent and an error. func newInlineTextContent(mediaType string, content any) (*InlineTextContent, error) { if mediaType != "text" && mediaType != "html" && mediaType != "" { return nil, fmt.Errorf("media type %v incompatible with inline text content", mediaType) @@ -36,12 +38,19 @@ func newInlineTextContent(mediaType string, content any) (*InlineTextContent, er return &InlineTextContent{Type: mediaType, Texts: texts}, nil } +// isContent checks whether the InlineTextContent is a Content. It returns a +// bool. func (i *InlineTextContent) isContent() bool { return true } +// hasSRC checks whether the InlineTextContent has a SRC attribute. It returns +// a bool. func (i *InlineTextContent) hasSRC() bool { return false } +// getType returns the Type of the InlineTextContent as a string. func (i *InlineTextContent) getType() string { return i.Type } +// Check checks the InlineTextContent for incompatibilities with RFC4287. It +// returns an error. func (i *InlineTextContent) Check() error { if i.Type != "" && i.Type != "text" && i.Type != "html" { return errors.New("type attribute of inline text content must be text or html if not omitted") diff --git a/inlineXHTMLContent.go b/inlineXHTMLContent.go index 41030be..6069df6 100644 --- a/inlineXHTMLContent.go +++ b/inlineXHTMLContent.go @@ -12,6 +12,8 @@ type InlineXHTMLContent struct { XHTMLDiv string `xml:"xhtmldiv"` } +// newInlineXHTMLContent creates a new InlineXHTMLContent. It returns a +// *InlineXHTMLContent and an error. func newInlineXHTMLContent(mediaType string, content any) (*InlineXHTMLContent, error) { if mediaType != "xhtml" { return nil, fmt.Errorf("media type %v incompatible with inline xhtml content", mediaType) @@ -24,12 +26,19 @@ func newInlineXHTMLContent(mediaType string, content any) (*InlineXHTMLContent, return &InlineXHTMLContent{Type: mediaType, XHTMLDiv: content.(string)}, nil } +// isContent checks whether the InlineXHTMLContent is a Content. It returns a +// bool. func (i *InlineXHTMLContent) isContent() bool { return true } +// hasSRC checks whether the InlineXHTMLContent has a SRC attribute. It returns +// a bool. func (i *InlineXHTMLContent) hasSRC() bool { return false } +// getType returns the Type of the InlineXHTMLContent as a string. func (i *InlineXHTMLContent) getType() string { return i.Type } +// Check checks the InlineXHTMLContent for incompatibilities with RFC4287. It +// returns an error. func (i *InlineXHTMLContent) Check() error { if i.Type != "xhtml" { return errors.New("type attribute of inline xhtml content must be xhtml") diff --git a/link.go b/link.go index c937aef..6956359 100644 --- a/link.go +++ b/link.go @@ -17,6 +17,7 @@ type Link struct { Length uint `xml:"length,attr,omitempty"` } +// NewLink creates a new Link. It returns a *Link and an error. func NewLink(href string) (*Link, error) { content, err := NewContent(InlineText, "", "") if err != nil { @@ -26,6 +27,8 @@ func NewLink(href string) (*Link, error) { return &Link{Href: IRI(href), Content: content}, nil } +// Check checks the Link for incompatibilities with RFC4287. It returns an +// error. func (l *Link) Check() error { if l.Href == "" { return errors.New("href attribute of link empty") @@ -58,6 +61,8 @@ func (l *Link) Check() error { return nil } +// hasAlternateDuplicateLinks checks whether multiple Links with Rel +// "alternate" also have Type and HrefLang in common. It returns a bool. // atom:feed/entry elements MUST NOT contain more than one atom:link element // with a rel attribute value of "alternate" that has the same combination of // type and hreflang attribute values. @@ -76,3 +81,15 @@ func hasAlternateDuplicateLinks(l []*Link) bool { return false } + +// alternateRelExists checks whether multiple Links with Rel "alternate" exist. +// It returns a bool. +func alternateRelExists(l []*Link) bool { + for _, link := range l { + if link.Rel == "alternate" { + return true + } + } + + return false +} diff --git a/logo.go b/logo.go index 949fbd5..19e305c 100644 --- a/logo.go +++ b/logo.go @@ -12,10 +12,13 @@ type Logo struct { URI IRI `xml:"uri"` } +// NewLogo creates a new Logo. It returns a *Logo. func NewLogo() *Logo { return &Logo{URI: IRI(fmt.Sprint("urn:uuid:", uuid.New()))} } +// Check checks the Logo for incompatibilities with RFC4287. It returns an +// error. func (l *Logo) Check() error { if l.URI == "" { return errors.New("uri element of logo empty") diff --git a/outOfLineContent.go b/outOfLineContent.go index 3a466c9..3a8bcfc 100644 --- a/outOfLineContent.go +++ b/outOfLineContent.go @@ -13,6 +13,8 @@ type OutOfLineContent struct { SRC IRI `xml:"src,attr"` } +// newOutOfLineContent creates a new OutOfLineContent. It returns a +// *OutOfLineContent and an error. func newOutOfLineContent(mediaType string, content any) (*OutOfLineContent, error) { if mediaType, _, err := mime.ParseMediaType(mediaType); err != nil { return nil, fmt.Errorf("media type %v incompatible with out of line content", mediaType) @@ -29,12 +31,19 @@ func newOutOfLineContent(mediaType string, content any) (*OutOfLineContent, erro return &OutOfLineContent{Type: MediaType(mediaType), SRC: content.(IRI)}, nil } +// isContent checks whether the OutOfLineContent is a Content. It returns a +// bool. func (o *OutOfLineContent) isContent() bool { return true } +// hasSRC checks whether the OutOfLineContent has a SRC attribute. It returns a +// bool. func (o *OutOfLineContent) hasSRC() bool { return true } +// getType returns the Type of the OutOfLineContent as a string. func (o *OutOfLineContent) getType() string { return string(o.Type) } +// Check checks the OutOfLineContent for incompatibilities with RFC4287. It +// returns an error. func (o *OutOfLineContent) Check() error { mediaType := o.getType() diff --git a/person.go b/person.go index 5eea6ea..177bb9f 100644 --- a/person.go +++ b/person.go @@ -14,11 +14,12 @@ type Person struct { Extensions []*ExtensionElement `xml:",any,omitempty"` } +// NewPerson creates a new Person. It returns a *Person. func NewPerson(name string) *Person { return &Person{Name: name} } -// AddExtension adds the extension to the person +// AddExtension adds the Extension to the Person. func (p *Person) AddExtension(e *ExtensionElement) { if p.Extensions == nil { p.Extensions = make([]*ExtensionElement, 1) @@ -28,6 +29,8 @@ func (p *Person) AddExtension(e *ExtensionElement) { } } +// Check checks the Person for incompatibilities with RFC4287. It returns an +// error. func (p *Person) Check() error { if p.Name == "" { return errors.New("name element of person element empty") diff --git a/plainText.go b/plainText.go index ff13bbc..78c47a0 100644 --- a/plainText.go +++ b/plainText.go @@ -8,8 +8,11 @@ type PlainText struct { Text string `xml:"text"` } +// isText checks whether the PlainText is a Text. It returns a bool. func (p *PlainText) isText() bool { return true } +// Check checks the PlainText for incompatibilities with RFC4287. It returns an +// error. func (p *PlainText) Check() error { if p.Type != "" && p.Type != "text" && p.Type != "html" { return errors.New("type attribute of plain text must be text or html if not omitted") diff --git a/source.go b/source.go index f17896f..c5e5f18 100644 --- a/source.go +++ b/source.go @@ -19,6 +19,8 @@ type Source struct { Extensions []*ExtensionElement `xml:",any,omitempty"` } +// Check checks the Source for incompatibilities with RFC4287. It returns an +// error. func (s *Source) Check() error { for i, a := range s.Authors { if err := a.Check(); err != nil { diff --git a/text.go b/text.go index 15004df..72225b3 100644 --- a/text.go +++ b/text.go @@ -10,6 +10,7 @@ type Text interface { Check() error } +// NewText creates a new Text. It returns a Text and an error. func NewText(textType, content string) (Text, error) { switch textType { case "text", "": diff --git a/xhtmlText.go b/xhtmlText.go index 82157f7..4573ee3 100644 --- a/xhtmlText.go +++ b/xhtmlText.go @@ -17,8 +17,11 @@ type XHTMLText struct { XHTMLDiv XHTMLDiv } +// isText checks whether the XHTMLText is a Text. It returns a bool. func (x *XHTMLText) isText() bool { return true } +// Check checks the XHTMLText for incompatibilities with RFC4287. It returns an +// error. func (x *XHTMLText) Check() error { if x.Type != "xhtml" { return errors.New("type attribute of xhtml text must be xhtml")