Compare commits

..

2 Commits

Author SHA1 Message Date
cf131f0bcf Touched up README 2024-10-20 15:10:58 +02:00
ae24db0c08 Clarified Add method's comments 2024-10-20 14:31:54 +02:00
7 changed files with 214 additions and 98 deletions

261
README.md
View File

@ -14,6 +14,8 @@ go get git.streifling.com/jason/atom@latest
## Usage
### Basic Feed
This library provides convenient functions to safely create, extend and delete
elements and attributes of Atom feeds. It also provides checks for all
constructs' adherence to RFC4287.
@ -22,37 +24,37 @@ constructs' adherence to RFC4287.
package main
import (
"fmt"
"log"
"fmt"
"log"
"git.streifling.com/jason/atom"
"git.streifling.com/jason/atom"
)
func main() {
feed := atom.NewFeed("Example Feed")
if err := feed.Check(); err != nil {
log.Fatalln(err)
}
feed := atom.NewFeed("Example Feed")
if err := feed.Check(); err != nil {
log.Fatalln(err)
}
author := atom.NewPerson("John Doe")
author.Email = "john.doe@example.com"
if err := author.Check(); err != nil {
log.Fatalln(err)
}
feed.AddAuthor(author)
author := atom.NewPerson("John Doe")
author.Email = "john.doe@example.com"
if err := author.Check(); err != nil {
log.Fatalln(err)
}
feed.AddAuthor(author)
entry := atom.NewEntry("First Entry")
entry.Content = atom.NewContent(atom.InlineText, "text", "This is the content of the first entry.")
if err := entry.Check(); err != nil {
log.Fatalln(err)
}
feed.AddEntry(entry)
entry := atom.NewEntry("First Entry")
entry.Content = atom.NewContent(atom.InlineText, "text", "This is the content of the first entry.")
if err := entry.Check(); err != nil {
log.Fatalln(err)
}
feed.AddEntry(entry)
feedString, err := feed.ToXML("utf-8")
if err != nil {
log.Fatalln(err)
}
fmt.Println(feedString)
feedString, err := feed.ToXML("UTF-8")
if err != nil {
log.Fatalln(err)
}
fmt.Println(feedString)
}
```
@ -63,70 +65,177 @@ provide.
package main
import (
"fmt"
"log"
"time"
"fmt"
"log"
"time"
"git.streifling.com/jason/atom"
"git.streifling.com/jason/atom"
"github.com/google/uuid"
)
func main() {
now := time.Now()
now := time.Now()
feed := &atom.Feed{
Title: &atom.PlainText{
Type: "text",
Text: "Example Feed",
},
ID: &atom.ID{URI: "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6"},
Updated: &atom.Date{DateTime: atom.DateTime(now)},
Authors: []*atom.Person{
{
Name: "John Doe",
Email: "john.doe@example.com",
},
},
Entries: []*atom.Entry{
{
Title: &atom.PlainText{
Type: "text",
Text: "First Entry",
},
ID: &atom.ID{URI: "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a"},
Updated: &atom.Date{DateTime: atom.DateTime(now)},
Content: &atom.InlineTextContent{
Type: "text",
Text: "This is the content of the first entry.",
},
},
},
}
feed := &atom.Feed{
Title: &atom.PlainText{
Type: "text",
Text: "Example Feed",
},
ID: &atom.ID{URI: fmt.Sprint("urn:uuid:", uuid.New())},
Updated: &atom.Date{DateTime: atom.DateTime(now)},
Authors: []*atom.Person{
{
Name: "John Doe",
Email: "john.doe@example.com",
},
},
Entries: []*atom.Entry{
{
Title: &atom.PlainText{
Type: "text",
Text: "First Entry",
},
ID: &atom.ID{URI: fmt.Sprint("urn:uuid:", uuid.New())},
Updated: &atom.Date{DateTime: atom.DateTime(now)},
Content: &atom.InlineTextContent{
Type: "text",
Text: "This is the content of the first entry.",
},
},
},
}
feedString, err := feed.ToXML("utf-8")
if err != nil {
log.Fatalln(err)
}
fmt.Println(feedString)
feedString, err := feed.ToXML("UTF-8")
if err != nil {
log.Fatalln(err)
}
fmt.Println(feedString)
}
```
The output of both ways of using it is an RFC4287 compliant Atom feed.
```xml
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<author>
<name>John Doe</name>
<email>john.doe@example.com</email>
</author>
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<title type="text">Example Feed</title>
<updated>2024-10-18T05:49:08+02:00</updated>
<entry>
<content type="text">This is the content of the first entry.</content>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<title type="text">First Entry</title>
<updated>2006-01-02T15:04:05+07:00</updated>
</entry>
<author>
<name>John Doe</name>
<email>john.doe@example.com</email>
</author>
<id>urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6</id>
<title type="text">Example Feed</title>
<updated>2024-10-18T05:49:08+02:00</updated>
<entry>
<content type="text">This is the content of the first entry.</content>
<id>urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a</id>
<title type="text">First Entry</title>
<updated>2006-01-02T15:04:05+07:00</updated>
</entry>
</feed>
```
### Compliance and Error Checking
All Atom constructs have their own ```construct.Check()``` method. It checks for
compliance with RFC4287 and errors. This allows one to be certain that only
compliant constructs are added to their respective parent construct. It also
means that not the entire feed has to be checked every time a new construct is
added. Instead one only checks the current construct and all of its
sub-constructs with a single ```construct.Check()``` call.
```go
package main
import (
"fmt"
"log"
"git.streifling.com/jason/atom"
)
func main() {
feed := atom.NewFeed("Example Feed")
if err := feed.Check(); err != nil {
log.Fatalln(err)
}
entry := atom.NewEntry("One")
entry.Content = atom.NewContent(atom.InlineText, "text", "Entry One")
entry.AddAuthor(atom.NewPerson("John Doe"))
if err := entry.Check(); err != nil {
log.Fatalln(err)
}
feed.AddEntry(entry)
feedString, err := feed.ToXML("UTF-8")
if err != nil {
log.Fatalln(err)
}
fmt.Println(feedString)
}
```
### Adding and Deleting Items
To add elements to any slice one calls the appropriate
```someone.AddSomething(toBeAdded)``` method. It returns the item's index
number. To delete the item one calls the Delete method.
```go
package main
import (
"fmt"
"log"
"git.streifling.com/jason/atom"
)
func main() {
feed := atom.NewFeed("Feed")
if err := feed.Check(); err != nil {
log.Fatalln(err)
}
e1 := atom.NewEntry("One")
e1.Content = atom.NewContent(atom.InlineText, "text", "Entry One")
if err := e1.Check(); err != nil {
log.Fatalln(err)
}
i1 := feed.AddEntry(e1)
e2 := atom.NewEntry("Two")
e2.Content = atom.NewContent(atom.InlineText, "text", "Entry Two")
if err := e2.Check(); err != nil {
log.Fatalln(err)
}
feed.AddEntry(e2)
if err := feed.DeleteEntry(i1); err != nil {
log.Fatalln(err)
}
feedString, err := feed.ToXML("UTF-8")
if err != nil {
log.Fatalln(err)
}
fmt.Println(feedString)
}
```
The output of this example looks like this. It only shows the second entry.
```xml
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<id>urn:uuid:ae89d343-b535-447d-ac14-4b80d3e02a2f</id>
<title type="text">Example Feed</title>
<updated>2024-10-20T14:57:02+02:00</updated>
<entry>
<content type="text">Entry Two</content>
<id>urn:uuid:620c6f73-ee1d-4c1e-be98-b0b1ad7a053f</id>
<title type="text">Two</title>
<updated>2024-10-20T14:57:02+02:00</updated>
</entry>
</feed>
```

View File

@ -21,8 +21,8 @@ func addToSlice[C Countable](slice *[]C, countable C) int {
if *slice == nil {
*slice = make([]C, 0)
}
*slice = append(*slice, countable)
*slice = append(*slice, countable)
return len(*slice) - 1
}

View File

@ -17,7 +17,8 @@ func newCommonAttributes() *CommonAttributes {
return new(CommonAttributes)
}
// AddAttribute adds the attribute to the CommonAttributes. It returns an int.
// AddAttribute adds the attribute to the CommonAttributes. It returns its index
// as an int.
func (c *CommonAttributes) AddAttribute(name, value string) int {
return addToSlice(&c.UndefinedAttributes, &xml.Attr{Name: xml.Name{Local: name}, Value: value})
}

View File

@ -66,7 +66,8 @@ func NewEntry(title string) *Entry {
}
}
// AddAuthor adds the Person as an author to the Entry. It returns an int.
// AddAuthor adds the Person as an author to the Entry. It returns its index as
// an int.
func (e *Entry) AddAuthor(p *Person) int {
e.Updated = NewDate(time.Now())
return addToSlice(&e.Authors, p)
@ -82,7 +83,7 @@ func (e *Entry) DeleteAuthor(index int) error {
return nil
}
// AddCategory adds the Category to the Entry. It returns an int.
// AddCategory adds the Category to the Entry. It returns ts index as an int.
func (e *Entry) AddCategory(c *Category) int {
e.Updated = NewDate(time.Now())
return addToSlice(&e.Categories, c)
@ -99,8 +100,8 @@ func (e *Entry) DeleteCategory(index int) error {
return nil
}
// AddContributor adds the Person as a contributor to the Entry. It returns an
// int.
// AddContributor adds the Person as a contributor to the Entry. It returns its
// index as an int.
func (e *Entry) AddContributor(c *Person) int {
e.Updated = NewDate(time.Now())
return addToSlice(&e.Contributors, c)
@ -117,7 +118,7 @@ func (e *Entry) DeleteContributor(index int) error {
return nil
}
// AddLink adds the Link to the Entry. It returns an int.
// AddLink adds the Link to the Entry. It returns its index as an int.
func (e *Entry) AddLink(l *Link) int {
e.Updated = NewDate(time.Now())
return addToSlice(&e.Links, l)
@ -133,7 +134,8 @@ func (e *Entry) DeleteLink(index int) error {
return nil
}
// AddExtension adds the ExtensionElement to the Entry. It returns an int.
// AddExtension adds the ExtensionElement to the Entry. It returns its index as
// an int.
func (e *Entry) AddExtension(x *ExtensionElement) int {
e.Updated = NewDate(time.Now())
return addToSlice(&e.Extensions, x)

15
feed.go
View File

@ -35,7 +35,8 @@ func NewFeed(title string) *Feed {
}
}
// AddAuthor adds the Person as an author to the Feed. It returns an int.
// AddAuthor adds the Person as an author to the Feed. It returns its index as
// an int.
func (f *Feed) AddAuthor(p *Person) int {
f.Updated = NewDate(time.Now())
return addToSlice(&f.Authors, p)
@ -51,7 +52,7 @@ func (f *Feed) DeleteAuthor(index int) error {
return nil
}
// AddCategory adds the Category to the Feed. It returns an int.
// AddCategory adds the Category to the Feed. It returns its index as an int.
func (f *Feed) AddCategory(c *Category) int {
f.Updated = NewDate(time.Now())
return addToSlice(&f.Categories, c)
@ -68,8 +69,8 @@ func (f *Feed) DeleteCategory(index int) error {
return nil
}
// AddContributor adds the Person as a contributor to the Feed. It returns an
// int.
// AddContributor adds the Person as a contributor to the Feed. It returns its
// index as an int.
func (f *Feed) AddContributor(c *Person) int {
f.Updated = NewDate(time.Now())
return addToSlice(&f.Contributors, c)
@ -87,7 +88,7 @@ func (f *Feed) DeleteContributor(index int) error {
}
// AddLink adds the Link to the Feed. There should be one Link with Rel "self".
// It returns an int.
// It returns its index as an int.
func (f *Feed) AddLink(l *Link) int {
f.Updated = NewDate(time.Now())
return addToSlice(&f.Links, l)
@ -103,7 +104,7 @@ func (f *Feed) DeleteLink(index int) error {
return nil
}
// AddExtension adds the Extension to the Feed. It returns an int.
// AddExtension adds the Extension to the Feed. It returns its index as an int.
func (f *Feed) AddExtension(e *ExtensionElement) int {
f.Updated = NewDate(time.Now())
return addToSlice(&f.Extensions, e)
@ -120,7 +121,7 @@ func (f *Feed) DeleteExtension(index int) error {
return nil
}
// AddEntry adds the Entry to the Feed. It returns an int.
// AddEntry adds the Entry to the Feed. It returns its index as an int.
func (f *Feed) AddEntry(e *Entry) int {
f.Updated = NewDate(time.Now())
return addToSlice(&f.Entries, e)

View File

@ -21,7 +21,8 @@ func NewPerson(name string) *Person {
}
}
// AddExtension adds the Extension to the Person. It returns an int.
// AddExtension adds the Extension to the Person. It returns its index as an
// int.
func (p *Person) AddExtension(e *ExtensionElement) int {
return addToSlice(&p.Extensions, e)
}

View File

@ -28,7 +28,8 @@ func NewSource() *Source {
return &Source{CommonAttributes: newCommonAttributes()}
}
// AddAuthor adds the Person as an author to the Source. It returns an int.
// AddAuthor adds the Person as an author to the Source. It returns its index as
// an int.
func (s *Source) AddAuthor(p *Person) int {
return addToSlice(&s.Authors, p)
}
@ -41,7 +42,7 @@ func (s *Source) DeleteAuthor(index int) error {
return nil
}
// AddCategory adds the Category to the Source. It returns an int.
// AddCategory adds the Category to the Source. It returns its index as an int.
func (s *Source) AddCategory(c *Category) int {
return addToSlice(&s.Categories, c)
}
@ -55,8 +56,8 @@ func (s *Source) DeleteCategory(index int) error {
return nil
}
// AddContributor adds the Person as a contributor to the Source. It returns an
// int.
// AddContributor adds the Person as a contributor to the Source. It returns its
// index as an int.
func (s *Source) AddContributor(c *Person) int {
return addToSlice(&s.Contributors, c)
}
@ -70,7 +71,7 @@ func (s *Source) DeleteContributor(index int) error {
return nil
}
// AddLink adds the Link to the Source. It returns an int.
// AddLink adds the Link to the Source. It returns its index as an int.
func (s *Source) AddLink(l *Link) int {
return addToSlice(&s.Links, l)
}
@ -83,7 +84,8 @@ func (s *Source) DeleteLink(index int) error {
return nil
}
// AddExtension adds the ExtensionElement to the Source. It returns an int.
// AddExtension adds the ExtensionElement to the Source. It returns its index as
// an int.
func (s *Source) AddExtension(e *ExtensionElement) int {
return addToSlice(&s.Extensions, e)
}