Skip to content

Commit

Permalink
feat: interface types
Browse files Browse the repository at this point in the history
  • Loading branch information
mingard committed Nov 3, 2022
1 parent 69ca95b commit 0669138
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 82 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#
USER=mingard
PACKAGE=sitemap-format
VERSION=1.1.0
VERSION=1.1.1

# Go command variables
GOCMD=go
Expand Down
21 changes: 21 additions & 0 deletions nodes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package sitemap

import (
"encoding/xml"
"time"
)

// ParentNode is the primary node e.g. <urlset> or <sitemap_index>
type ParentNode interface {
SetType(t *xml.Attr)
AddEntry(sm ChildNode)
}

// Childnode is the nested node type e.g. <url> or <sitemap>
type ChildNode interface {
SetLocation(l string)
SetLastModified(t time.Time)
SetNews(n *News)
AddImage(i ...*Image)
AddVideo(v ...*Video)
}
18 changes: 11 additions & 7 deletions sitemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,29 @@ type Sitemap struct {
}

// SetLocation sets the sitemap's location parameter
func (s *Sitemap) SetLocation(l string) *Sitemap {
func (s *Sitemap) SetLocation(l string) {
s.Location = l
return s
}

// SetLastModified sets the value of the modified date field.
func (s *Sitemap) SetLastModified(t time.Time) *Sitemap {
func (s *Sitemap) SetLastModified(t time.Time) {
s.LastModifiedDate = t.UTC()
return s
}

// Defaults
func (s *Sitemap) SetNews(n *News) {}
func (s *Sitemap) AddImage(i ...*Image) {}
func (s *Sitemap) AddVideo(v ...*Video) {}

// defaultSitemap creates a default sitemap entity with required values.
func defaultSitemap() *Sitemap {
func defaultSitemap() ChildNode {
now := time.Now()
sitemap := new(Sitemap)
return sitemap.SetLastModified(now)
sitemap.SetLastModified(now)
return sitemap
}

// NewSitemap returns a new instance of the default sitemap.
func NewSitemap() *Sitemap {
func NewSitemap() ChildNode {
return defaultSitemap()
}
14 changes: 7 additions & 7 deletions sitemap_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,28 @@ import "encoding/xml"
type SitemapIndex struct {
XMLName xml.Name `xml:"sitemapindex"`
Attributes []*xml.Attr `xml:",attr,omitempty"`
Sitemap []*Sitemap `xml:"sitemap,omitempty"`
Sitemap []ChildNode `xml:"sitemap,omitempty"`
}

// SetType sets the sitemapindex xml namespace type.
func (s *SitemapIndex) SetType(t *xml.Attr) {
s.Attributes = append(s.Attributes, t)
}

// AddSitemap inserts a sitemap node into the XML's Sitemap node.
func (s *SitemapIndex) AddSitemap(sm *Sitemap) {
// AddEntry inserts a sitemap node into the XML's Sitemap node.
func (s *SitemapIndex) AddEntry(sm ChildNode) {
s.Sitemap = append(s.Sitemap, sm)
}

// defaultSitemapIndex creates a default sitemapindex entity with required values.
func defaultSitemapIndex() *SitemapIndex {
func defaultSitemapIndex() ParentNode {
return &SitemapIndex{
Attributes: []*xml.Attr{XMLNSDefault},
Sitemap: make([]*Sitemap, 0),
Sitemap: make([]ChildNode, 0),
}
}

// NewSitemapIndex returns a new instance of the default SitemapIndex.
func NewSitemapIndex() *SitemapIndex {
// NewIndex returns a new instance of the default SitemapIndex.
func NewIndex() ParentNode {
return defaultSitemapIndex()
}
25 changes: 17 additions & 8 deletions sitemap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import (
)

const (
testDefaultXML string = `<?xml version="1.0" encoding="UTF-8"?>`
testDefaultPrettyXML string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\nXXXXX<url>\nXXXXXXXXXX<lastmod>2021-08-15T14:30:45.0000001Z</lastmod>\nXXXXX</url>\n</urlset>"
testDefaultXML string = `<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></urlset>`
testDefaultSitemapIndexXML string = `<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></sitemapindex>`
testDefaultPrettyXML string = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\nXXXXX<url>\nXXXXXXXXXX<lastmod>2021-08-15T14:30:45.0000001Z</lastmod>\nXXXXX</url>\n</urlset>"
)

func getDoc(str string) (*xmlquery.Node, error) {
Expand Down Expand Up @@ -41,13 +42,21 @@ func TestDefaults(t *testing.T) {
assert.Equal(t, testDefaultXML, out, "Should output default empty XML")
}

func TestNewSitemapIndex(t *testing.T) {
xml := NewSitemapIndex()

out, _ := xml.OutputString()

assert.Equal(t, testDefaultSitemapIndexXML, out, "Should output default empty XML")
}

func TestPrettyOutput(t *testing.T) {
xml := New()

url := NewUrl()
fixedTime := time.Date(2021, 8, 15, 14, 30, 45, 100, time.UTC)
url.SetLastModified(fixedTime)
xml.AddUrl(url)
xml.AddEntry(url)

out, _ := xml.OutputPrettyString("", "XXXXX")

Expand All @@ -58,7 +67,7 @@ func TestXMLAddDefaultUrl(t *testing.T) {
xml := New()
url := NewUrl()

xml.AddUrl(url)
xml.AddEntry(url)

out, _ := xml.OutputString()

Expand All @@ -68,12 +77,12 @@ func TestXMLAddDefaultUrl(t *testing.T) {
assert.True(t, lastModTag != nil, "Should have default last modified")
}

func TestXMLAddUrlWithLocation(t *testing.T) {
func TestXMLAddEntryWithLocation(t *testing.T) {
xml := New()
url := NewUrl()

url.SetLocation("https://domain.com")
xml.AddUrl(url)
xml.AddEntry(url)

out, _ := xml.OutputString()
tag, _ := findOne(out, "//urlset/url/loc")
Expand All @@ -97,14 +106,14 @@ func TestSetType(t *testing.T) {
assert.Equal(t, doc.InnerText(), XMLNSNews.Value, "Should contain correct type")
}

func TestXMLAddUrlWithLastModified(t *testing.T) {
func TestXMLAddEntryWithLastModified(t *testing.T) {
xml := New()
url := NewUrl()

now := time.Now()
later := now.Add(3 * time.Hour)
url.SetLastModified(later)
xml.AddUrl(url)
xml.AddEntry(url)

out, _ := xml.OutputString()

Expand Down
22 changes: 9 additions & 13 deletions url.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,46 +18,42 @@ type Url struct {
}

// SetLocation sets the url's location parameter
func (u *Url) SetLocation(l string) *Url {
func (u *Url) SetLocation(l string) {
u.Location = l
return u
}

// SetLastModified sets the value of the modified date field.
func (u *Url) SetLastModified(t time.Time) *Url {
func (u *Url) SetLastModified(t time.Time) {
u.LastModifiedDate = t.UTC()
return u
}

// SetNews sets the news value.
func (u *Url) SetNews(n *News) *Url {
func (u *Url) SetNews(n *News) {
u.News = n
return u
}

// AddImage adds one or more image block value.
func (u *Url) AddImage(i ...*Image) *Url {
func (u *Url) AddImage(i ...*Image) {
u.Images = append(u.Images, i...)
return u
}

// AddVideo adds one or more video block value.
func (u *Url) AddVideo(v ...*Video) *Url {
func (u *Url) AddVideo(v ...*Video) {
u.Videos = append(u.Videos, v...)
return u
}

// defaultUrl creates a default url entity with required values.
func defaultUrl() *Url {
func defaultUrl() ChildNode {
now := time.Now()
url := &Url{
Images: make([]*Image, 0),
Videos: make([]*Video, 0),
}
return url.SetLastModified(now)
url.SetLastModified(now)
return url
}

// NewUrl returns a new instance of the default URL.
func NewUrl() *Url {
func NewUrl() ChildNode {
return defaultUrl()
}
12 changes: 6 additions & 6 deletions url_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,28 @@ import "encoding/xml"
type UrlSet struct {
XMLName xml.Name `xml:"urlset"`
Attributes []*xml.Attr `xml:",attr,omitempty"`
Url []*Url `xml:"url,omitempty"`
Url []ChildNode `xml:"url,omitempty"`
}

// SetType sets the urlset xml namespace type.
func (u *UrlSet) SetType(t *xml.Attr) {
u.Attributes = append(u.Attributes, t)
}

// AddUrl inserts a URL node into the XML's UrlSet node.
func (u *UrlSet) AddUrl(url *Url) {
// AddEntry inserts a URL node into the XML's UrlSet node.
func (u *UrlSet) AddEntry(url ChildNode) {
u.Url = append(u.Url, url)
}

// defaultUrlSet creates a default urlset entity with required values.
func defaultUrlSet() *UrlSet {
func defaultUrlSet() ParentNode {
return &UrlSet{
Attributes: []*xml.Attr{XMLNSDefault},
Url: make([]*Url, 0),
Url: make([]ChildNode, 0),
}
}

// NewUrlSet returns a new instance of the default UrlSet.
func NewUrlSet() *UrlSet {
func NewUrlSet() ParentNode {
return defaultUrlSet()
}
60 changes: 20 additions & 40 deletions xml.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,35 @@ const (

// SitemapXML is the top level XML node for the sitemap
type SitemapXML struct {
UrlSet []*UrlSet `xml:"urlset,omitempty"`
SitemapIndex []*SitemapIndex `xml:"sitemapindex,omitempty"`
ParentNodes []ParentNode `xml:",omitempty"`
pretty bool
outputPrefix string
outputIndent string
}

// AddUrl inserts a URL node into the XML's UrlSet node.
func (s *SitemapXML) AddUrl(u *Url) {
s.addDefaultUrlSet()
s.UrlSet[0].AddUrl(u)
}

func (s *SitemapXML) AddSitemap(sm *Sitemap) {
s.addDefaultSitemapIndex()
s.SitemapIndex[0].AddSitemap(sm)
func (s *SitemapXML) AddEntry(e ChildNode) {
s.ParentNodes[0].AddEntry(e)
}

// SetType sets the urlset type and creates a default urlset if necessary.
func (s *SitemapXML) SetType(t *xml.Attr) {
s.addDefaultUrlSet()
s.UrlSet[0].SetType(t)
for _, parent := range s.ParentNodes {
parent.SetType(t)
}
}

// Output returns the output value as bytes
func (s *SitemapXML) Output() ([]byte, error) {
out := []byte(s.headerString())
var err error
var subject any

if s.UrlSet != nil {
subject = s.UrlSet
} else if s.SitemapIndex != nil {
subject = s.SitemapIndex
} else {
return out, err
}

var marshalledXML []byte

if s.pretty {
marshalledXML, err = xml.MarshalIndent(subject, s.outputPrefix, s.outputIndent)
marshalledXML, err = xml.MarshalIndent(s.ParentNodes, s.outputPrefix, s.outputIndent)
} else {
marshalledXML, err = xml.Marshal(subject)
marshalledXML, err = xml.Marshal(s.ParentNodes)
}

if err == nil {
Expand Down Expand Up @@ -86,20 +71,6 @@ func (s *SitemapXML) OutputPrettyString(prefix, indent string) (string, error) {
return s.OutputString()
}

func (s *SitemapXML) addDefaultUrlSet() {
if len(s.UrlSet) == 0 {
urlSet := NewUrlSet()
s.UrlSet = append(s.UrlSet, urlSet)
}
}

func (s *SitemapXML) addDefaultSitemapIndex() {
if len(s.SitemapIndex) == 0 {
sitemapIndex := NewSitemapIndex()
s.SitemapIndex = append(s.SitemapIndex, sitemapIndex)
}
}

// headerString outputs the XML header string
func (s *SitemapXML) headerString() string {
xmlHeader := fmt.Sprintf(`<?xml version="%s" encoding="%s"?>`, defaultVersion, defaultEncoding)
Expand All @@ -112,14 +83,23 @@ func (s *SitemapXML) headerString() string {
// defaultXML creates a default xml entity with required values.
func defaultXML() *SitemapXML {
return &SitemapXML{
UrlSet: make([]*UrlSet, 0),
SitemapIndex: make([]*SitemapIndex, 0),
ParentNodes: make([]ParentNode, 0),
outputPrefix: defaultOutputPrefix,
outputIndent: defaultOutputIndent,
}
}

func NewSitemapIndex() *SitemapXML {
sitemapIndex := NewIndex()
out := defaultXML()
out.ParentNodes = append(out.ParentNodes, sitemapIndex)
return out
}

// New returns a new instance of the default XML.
func New() *SitemapXML {
return defaultXML()
urlSet := NewUrlSet()
out := defaultXML()
out.ParentNodes = append(out.ParentNodes, urlSet)
return out
}

0 comments on commit 0669138

Please sign in to comment.