Added and corrected comments

This commit is contained in:
Jason Streifling 2024-10-16 19:59:28 +02:00
parent 6a76bdc0c3
commit 4220a2acc6
23 changed files with 131 additions and 39 deletions

13
atom.go
View File

@ -31,14 +31,16 @@ type (
// return isValidURL(uri) || isValidURN(uri) // 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 // 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 { 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])|[!$&'()*+,;=:@])|/|\?))*))?)` 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)) 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 { func isCorrectlyEscaped(text string) bool {
relevantEntities := []string{"&", "<", ">", """, "'"} relevantEntities := []string{"&", "<", ">", """, "'"}
@ -51,6 +53,8 @@ func isCorrectlyEscaped(text string) bool {
return true return true
} }
// isCompositeMediaType checks whether a string is a composite media type. It
// returns a bool.
func isCompositeMediaType(mediaType string) bool { func isCompositeMediaType(mediaType string) bool {
mediaType, _, err := mime.ParseMediaType(mediaType) mediaType, _, err := mime.ParseMediaType(mediaType)
if err != nil { if err != nil {
@ -60,6 +64,8 @@ func isCompositeMediaType(mediaType string) bool {
return strings.HasPrefix(mediaType, "multipart/") || strings.HasPrefix(mediaType, "message/") 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 { func isXMLMediaType(mediaType string) bool {
mediaType, _, err := mime.ParseMediaType(mediaType) mediaType, _, err := mime.ParseMediaType(mediaType)
if err != nil { if err != nil {
@ -69,11 +75,14 @@ func isXMLMediaType(mediaType string) bool {
return strings.HasSuffix(mediaType, "/xml") || strings.HasSuffix(mediaType, "+xml") 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 { func isValidMediaType(mediaType string) bool {
_, _, err := mime.ParseMediaType(mediaType) _, _, err := mime.ParseMediaType(mediaType)
return err == nil return err == nil
} }
// isValidLanguageTag checks whether a LanguageTag is valid. It returns a bool.
func isValidLanguageTag(tag LanguageTag) bool { func isValidLanguageTag(tag LanguageTag) bool {
_, err := language.Parse(string(tag)) _, err := language.Parse(string(tag))
return err == nil return err == nil

View File

@ -14,6 +14,7 @@ type Category struct {
Label string `xml:"label,attr,omitempty"` Label string `xml:"label,attr,omitempty"`
} }
// NewCategory creates a new Category. It returns a *Category and an error.
func NewCategory(term string) (*Category, error) { func NewCategory(term string) (*Category, error) {
content, err := NewContent(InlineText, "", "") content, err := NewContent(InlineText, "", "")
if err != nil { if err != nil {
@ -23,10 +24,13 @@ func NewCategory(term string) (*Category, error) {
return &Category{Term: term, Content: content}, nil return &Category{Term: term, Content: content}, nil
} }
// SetLabel sets the label of the Category.
func (c *Category) SetLabel(label string) { func (c *Category) SetLabel(label string) {
c.Label = html.UnescapeString(label) c.Label = html.UnescapeString(label)
} }
// Check checks the Category for incompatibilities with RFC4287. It returns an
// error.
func (c *Category) Check() error { func (c *Category) Check() error {
if c.Term == "" { if c.Term == "" {
return errors.New("term attribute of category empty") return errors.New("term attribute of category empty")

View File

@ -8,6 +8,8 @@ type CommonAttributes struct {
UndefinedAttributes []*ExtensionAttribute `xml:",any"` UndefinedAttributes []*ExtensionAttribute `xml:",any"`
} }
// Check checks the CommonAttributes for incompatibilities with RFC4287. It
// returns an error.
func (c *CommonAttributes) Check() error { func (c *CommonAttributes) Check() error {
for i, e := range c.UndefinedAttributes { for i, e := range c.UndefinedAttributes {
if err := e.Check(); err != nil { if err := e.Check(); err != nil {

View File

@ -18,6 +18,7 @@ type Content interface {
Check() error Check() error
} }
// NewContent creates a new Content. It returns a Content and an error.
func NewContent(contentType int, mediaType string, content any) (Content, error) { func NewContent(contentType int, mediaType string, content any) (Content, error) {
switch contentType { switch contentType {
case 0: case 0:

View File

@ -10,14 +10,19 @@ type Date struct {
DateTime string DateTime string
} }
// DateTime formats a time.Time to string formated as defined by RFC3339. It
// returns a string.
func DateTime(t time.Time) string { func DateTime(t time.Time) string {
return string(t.Format(time.RFC3339)) return string(t.Format(time.RFC3339))
} }
// NewDate creates a new Date. It returns a *Date.
func NewDate(t time.Time) *Date { func NewDate(t time.Time) *Date {
return &Date{DateTime: DateTime(t)} return &Date{DateTime: DateTime(t)}
} }
// Check checks the Date for incompatibilities with RFC4287. It returns an
// error.
func (d *Date) Check() error { func (d *Date) Check() error {
if d.DateTime == "" { if d.DateTime == "" {
return errors.New("date time element of date is empty") return errors.New("date time element of date is empty")

View File

@ -28,6 +28,8 @@ type Entry struct {
Extensions []*ExtensionElement `xml:",any,omitempty"` 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 // 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 // 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 // element or, in an Atom Feed Document, the atom:feed element contains an
@ -48,17 +50,21 @@ func (e *Entry) checkAuthors() error {
return nil return nil
} }
func alternateRelExists(l []*Link) bool { // NewEntry creates a new Entry. It returns a *Entry and an error.
for _, link := range l { func NewEntry(title string) (*Entry, error) {
if link.Rel == "alternate" { text, err := NewText("text", title)
return true 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) { func (e *Entry) AddExtension(x *ExtensionElement) {
if e.Extensions == nil { if e.Extensions == nil {
e.Extensions = make([]*ExtensionElement, 1) e.Extensions = make([]*ExtensionElement, 1)
@ -70,6 +76,8 @@ func (e *Entry) AddExtension(x *ExtensionElement) {
e.Updated.DateTime = DateTime(time.Now()) e.Updated.DateTime = DateTime(time.Now())
} }
// Check checks the Entry for incompatibilities with RFC4287. It returns an
// error.
func (e *Entry) Check() error { func (e *Entry) Check() error {
if e.ID == nil { if e.ID == nil {
return errors.New("no id element of entry") return errors.New("no id element of entry")

View File

@ -10,6 +10,8 @@ type ExtensionAttribute struct {
XMLName xml.Name XMLName xml.Name
} }
// Check checks the ExtensionAttribute for incompatibilities with RFC4287. It
// returns an error.
func (e *ExtensionAttribute) Check() error { func (e *ExtensionAttribute) Check() error {
if e.Value == nil { if e.Value == nil {
return errors.New("value element of extension attribute empty") return errors.New("value element of extension attribute empty")

View File

@ -10,10 +10,14 @@ type ExtensionElement struct {
XMLName xml.Name XMLName xml.Name
} }
// NewExtensionElement creates a new ExtensionElement. It returns a
// *ExtensionElement.
func NewExtensionElement(name string, value any) *ExtensionElement { func NewExtensionElement(name string, value any) *ExtensionElement {
return &ExtensionElement{XMLName: xml.Name{Local: name}, Value: value} 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 { func (e *ExtensionElement) Check() error {
if e.Value == nil { if e.Value == nil {
return errors.New("value element of extension element empty") return errors.New("value element of extension element empty")

39
feed.go
View File

@ -26,7 +26,7 @@ type Feed struct {
Entries []*Entry `xml:"entry,omitempty"` 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) { func NewFeed(title string) (*Feed, error) {
text, err := NewText("text", title) text, err := NewText("text", title)
if err != nil { if err != nil {
@ -40,7 +40,7 @@ func NewFeed(title string) (*Feed, error) {
}, nil }, 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) { func (f *Feed) AddAuthor(p *Person) {
if f.Authors == nil { if f.Authors == nil {
f.Authors = make([]*Person, 1) f.Authors = make([]*Person, 1)
@ -52,7 +52,7 @@ func (f *Feed) AddAuthor(p *Person) {
f.Updated.DateTime = DateTime(time.Now()) 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) { func (f *Feed) AddCategory(c *Category) {
if f.Categories == nil { if f.Categories == nil {
f.Categories = make([]*Category, 1) f.Categories = make([]*Category, 1)
@ -64,7 +64,7 @@ func (f *Feed) AddCategory(c *Category) {
f.Updated.DateTime = DateTime(time.Now()) 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) { func (f *Feed) AddContributor(c *Person) {
if f.Contributors == nil { if f.Contributors == nil {
f.Contributors = make([]*Person, 1) f.Contributors = make([]*Person, 1)
@ -76,8 +76,7 @@ func (f *Feed) AddContributor(c *Person) {
f.Updated.DateTime = DateTime(time.Now()) f.Updated.DateTime = DateTime(time.Now())
} }
// AddLink adds the link to the feed. // AddLink adds the Link to the Feed. There should be one Link with Rel "self".
// There should be one link with rel "self".
func (f *Feed) AddLink(l *Link) { func (f *Feed) AddLink(l *Link) {
if f.Links == nil { if f.Links == nil {
f.Links = make([]*Link, 1) f.Links = make([]*Link, 1)
@ -89,7 +88,7 @@ func (f *Feed) AddLink(l *Link) {
f.Updated.DateTime = DateTime(time.Now()) 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) { func (f *Feed) AddExtension(e *ExtensionElement) {
if f.Extensions == nil { if f.Extensions == nil {
f.Extensions = make([]*ExtensionElement, 1) f.Extensions = make([]*ExtensionElement, 1)
@ -101,7 +100,7 @@ func (f *Feed) AddExtension(e *ExtensionElement) {
f.Updated.DateTime = DateTime(time.Now()) 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) { func (f *Feed) AddEntry(e *Entry) {
if f.Entries == nil { if f.Entries == nil {
f.Entries = make([]*Entry, 1) f.Entries = make([]*Entry, 1)
@ -113,7 +112,8 @@ func (f *Feed) AddEntry(e *Entry) {
f.Updated.DateTime = DateTime(time.Now()) 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 { func (f *Feed) Check() error {
if f.ID == nil { if f.ID == nil {
return errors.New("no id element of feed") return errors.New("no id element of feed")
@ -222,26 +222,7 @@ func (f *Feed) Check() error {
return nil return nil
} }
// TODO: Create complete link or delete // ToXML converts the Feed to XML. It returns a string and an error.
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.
func (f *Feed) ToXML(encoding string) (string, error) { func (f *Feed) ToXML(encoding string) (string, error) {
xml, err := xml.MarshalIndent(f, "", " ") xml, err := xml.MarshalIndent(f, "", " ")
if err != nil { if err != nil {

View File

@ -13,10 +13,13 @@ type Generator struct {
Text string `xml:"text"` Text string `xml:"text"`
} }
// NewGenerator creates a new Generator. It returns a *Generator.
func NewGenerator(text string) *Generator { func NewGenerator(text string) *Generator {
return &Generator{Text: html.UnescapeString(text)} return &Generator{Text: html.UnescapeString(text)}
} }
// Check checks the Generator for incompatibilities with RFC4287. It returns an
// error.
func (g *Generator) Check() error { func (g *Generator) Check() error {
if g.URI != "" { if g.URI != "" {
if !isValidIRI(g.URI) { if !isValidIRI(g.URI) {

View File

@ -10,10 +10,13 @@ type Icon struct {
URI IRI `xml:"uri"` URI IRI `xml:"uri"`
} }
// NewIcon creates a new Icon. It returns a *Icon.
func NewIcon(uri string) *Icon { func NewIcon(uri string) *Icon {
return &Icon{URI: IRI(uri)} return &Icon{URI: IRI(uri)}
} }
// Check checks the Icon for incompatibilities with RFC4287. It returns an
// error.
func (i *Icon) Check() error { func (i *Icon) Check() error {
if i.URI == "" { if i.URI == "" {
return errors.New("uri element of icon empty") return errors.New("uri element of icon empty")

2
id.go
View File

@ -12,10 +12,12 @@ type ID struct {
URI IRI `xml:"uri"` URI IRI `xml:"uri"`
} }
// NewID creates a new ID. It returns a *ID.
func NewID() *ID { func NewID() *ID {
return &ID{URI: IRI(fmt.Sprint("urn:uuid:", uuid.New()))} 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 { func (i *ID) Check() error {
if i.URI == "" { if i.URI == "" {
return errors.New("uri element of id empty") return errors.New("uri element of id empty")

View File

@ -12,6 +12,8 @@ type InlineOtherContent struct {
Type MediaType `xml:"type,attr,omitempty"` 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) { func newInlineOtherContent(mediaType string, content any) (*InlineOtherContent, error) {
if mediaType, _, err := mime.ParseMediaType(mediaType); err != nil { if mediaType, _, err := mime.ParseMediaType(mediaType); err != nil {
return nil, fmt.Errorf("media type %v incompatible with inline other content", mediaType) 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 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 } 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 } 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) } 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 { func (i *InlineOtherContent) Check() error {
mediaType := i.getType() mediaType := i.getType()

View File

@ -12,6 +12,8 @@ type InlineTextContent struct {
Texts []string `xml:"texts,omitempty"` 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) { func newInlineTextContent(mediaType string, content any) (*InlineTextContent, error) {
if mediaType != "text" && mediaType != "html" && mediaType != "" { if mediaType != "text" && mediaType != "html" && mediaType != "" {
return nil, fmt.Errorf("media type %v incompatible with inline text content", 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 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 } 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 } 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 } 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 { func (i *InlineTextContent) Check() error {
if i.Type != "" && i.Type != "text" && i.Type != "html" { 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") return errors.New("type attribute of inline text content must be text or html if not omitted")

View File

@ -12,6 +12,8 @@ type InlineXHTMLContent struct {
XHTMLDiv string `xml:"xhtmldiv"` XHTMLDiv string `xml:"xhtmldiv"`
} }
// newInlineXHTMLContent creates a new InlineXHTMLContent. It returns a
// *InlineXHTMLContent and an error.
func newInlineXHTMLContent(mediaType string, content any) (*InlineXHTMLContent, error) { func newInlineXHTMLContent(mediaType string, content any) (*InlineXHTMLContent, error) {
if mediaType != "xhtml" { if mediaType != "xhtml" {
return nil, fmt.Errorf("media type %v incompatible with inline xhtml content", mediaType) 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 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 } 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 } 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 } 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 { func (i *InlineXHTMLContent) Check() error {
if i.Type != "xhtml" { if i.Type != "xhtml" {
return errors.New("type attribute of inline xhtml content must be xhtml") return errors.New("type attribute of inline xhtml content must be xhtml")

17
link.go
View File

@ -17,6 +17,7 @@ type Link struct {
Length uint `xml:"length,attr,omitempty"` Length uint `xml:"length,attr,omitempty"`
} }
// NewLink creates a new Link. It returns a *Link and an error.
func NewLink(href string) (*Link, error) { func NewLink(href string) (*Link, error) {
content, err := NewContent(InlineText, "", "") content, err := NewContent(InlineText, "", "")
if err != nil { if err != nil {
@ -26,6 +27,8 @@ func NewLink(href string) (*Link, error) {
return &Link{Href: IRI(href), Content: content}, nil 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 { func (l *Link) Check() error {
if l.Href == "" { if l.Href == "" {
return errors.New("href attribute of link empty") return errors.New("href attribute of link empty")
@ -58,6 +61,8 @@ func (l *Link) Check() error {
return nil 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 // 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 // with a rel attribute value of "alternate" that has the same combination of
// type and hreflang attribute values. // type and hreflang attribute values.
@ -76,3 +81,15 @@ func hasAlternateDuplicateLinks(l []*Link) bool {
return false 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
}

View File

@ -12,10 +12,13 @@ type Logo struct {
URI IRI `xml:"uri"` URI IRI `xml:"uri"`
} }
// NewLogo creates a new Logo. It returns a *Logo.
func NewLogo() *Logo { func NewLogo() *Logo {
return &Logo{URI: IRI(fmt.Sprint("urn:uuid:", uuid.New()))} 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 { func (l *Logo) Check() error {
if l.URI == "" { if l.URI == "" {
return errors.New("uri element of logo empty") return errors.New("uri element of logo empty")

View File

@ -13,6 +13,8 @@ type OutOfLineContent struct {
SRC IRI `xml:"src,attr"` 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) { func newOutOfLineContent(mediaType string, content any) (*OutOfLineContent, error) {
if mediaType, _, err := mime.ParseMediaType(mediaType); err != nil { if mediaType, _, err := mime.ParseMediaType(mediaType); err != nil {
return nil, fmt.Errorf("media type %v incompatible with out of line content", mediaType) 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 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 } 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 } 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) } 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 { func (o *OutOfLineContent) Check() error {
mediaType := o.getType() mediaType := o.getType()

View File

@ -14,11 +14,12 @@ type Person struct {
Extensions []*ExtensionElement `xml:",any,omitempty"` Extensions []*ExtensionElement `xml:",any,omitempty"`
} }
// NewPerson creates a new Person. It returns a *Person.
func NewPerson(name string) *Person { func NewPerson(name string) *Person {
return &Person{Name: name} return &Person{Name: name}
} }
// AddExtension adds the extension to the person // AddExtension adds the Extension to the Person.
func (p *Person) AddExtension(e *ExtensionElement) { func (p *Person) AddExtension(e *ExtensionElement) {
if p.Extensions == nil { if p.Extensions == nil {
p.Extensions = make([]*ExtensionElement, 1) 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 { func (p *Person) Check() error {
if p.Name == "" { if p.Name == "" {
return errors.New("name element of person element empty") return errors.New("name element of person element empty")

View File

@ -8,8 +8,11 @@ type PlainText struct {
Text string `xml:"text"` Text string `xml:"text"`
} }
// isText checks whether the PlainText is a Text. It returns a bool.
func (p *PlainText) isText() bool { return true } func (p *PlainText) isText() bool { return true }
// Check checks the PlainText for incompatibilities with RFC4287. It returns an
// error.
func (p *PlainText) Check() error { func (p *PlainText) Check() error {
if p.Type != "" && p.Type != "text" && p.Type != "html" { 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") return errors.New("type attribute of plain text must be text or html if not omitted")

View File

@ -19,6 +19,8 @@ type Source struct {
Extensions []*ExtensionElement `xml:",any,omitempty"` Extensions []*ExtensionElement `xml:",any,omitempty"`
} }
// Check checks the Source for incompatibilities with RFC4287. It returns an
// error.
func (s *Source) Check() error { func (s *Source) Check() error {
for i, a := range s.Authors { for i, a := range s.Authors {
if err := a.Check(); err != nil { if err := a.Check(); err != nil {

View File

@ -10,6 +10,7 @@ type Text interface {
Check() error Check() error
} }
// NewText creates a new Text. It returns a Text and an error.
func NewText(textType, content string) (Text, error) { func NewText(textType, content string) (Text, error) {
switch textType { switch textType {
case "text", "": case "text", "":

View File

@ -17,8 +17,11 @@ type XHTMLText struct {
XHTMLDiv XHTMLDiv XHTMLDiv XHTMLDiv
} }
// isText checks whether the XHTMLText is a Text. It returns a bool.
func (x *XHTMLText) isText() bool { return true } func (x *XHTMLText) isText() bool { return true }
// Check checks the XHTMLText for incompatibilities with RFC4287. It returns an
// error.
func (x *XHTMLText) Check() error { func (x *XHTMLText) Check() error {
if x.Type != "xhtml" { if x.Type != "xhtml" {
return errors.New("type attribute of xhtml text must be xhtml") return errors.New("type attribute of xhtml text must be xhtml")