Compare commits
	
		
			18 Commits
		
	
	
		
			v0.1.3
			...
			e73b78ef30
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e73b78ef30 | |||
| 5a82f1799f | |||
| 73624eadd8 | |||
| 17aa4b1a15 | |||
| 040d7a6b7b | |||
| 705b651f08 | |||
| 4b97bf7fdc | |||
| 86785be588 | |||
| 28f5616f76 | |||
| 657624cbd6 | |||
| b496ac3691 | |||
| 13e7a16178 | |||
| 3734a3eb3d | |||
| e0902d9ba4 | |||
| 434783165b | |||
| 46138d302b | |||
| 6b9d5be734 | |||
| 2ef8d8c9df | 
							
								
								
									
										27
									
								
								atom.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								atom.go
									
									
									
									
									
								
							| @@ -1,10 +1,13 @@ | |||||||
| package atom | package atom | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"encoding/xml" | ||||||
|  | 	"fmt" | ||||||
| 	"mime" | 	"mime" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
|  | 	"github.com/google/uuid" | ||||||
| 	"golang.org/x/text/language" | 	"golang.org/x/text/language" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -61,8 +64,17 @@ func isXMLMediaType(mediaType string) bool { | |||||||
| // isValidMediaType checks whether a string is a valid media type. It returns a | // isValidMediaType checks whether a string is a valid media type. It returns a | ||||||
| // bool. | // bool. | ||||||
| func isValidMediaType(mediaType string) bool { | func isValidMediaType(mediaType string) bool { | ||||||
| 	_, _, err := mime.ParseMediaType(mediaType) | 	mediaType, _, err := mime.ParseMediaType(mediaType) | ||||||
| 	return err == nil | 	if err != nil { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	typeParts := strings.Split(mediaType, "/") | ||||||
|  | 	if len(typeParts) != 2 || typeParts[0] == "" || typeParts[1] == "" { | ||||||
|  | 		return false | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return true | ||||||
| } | } | ||||||
|  |  | ||||||
| // isValidLanguageTag checks whether a LanguageTag is valid. It returns a bool. | // isValidLanguageTag checks whether a LanguageTag is valid. It returns a bool. | ||||||
| @@ -70,3 +82,14 @@ func isValidLanguageTag(tag LanguageTag) bool { | |||||||
| 	_, err := language.Parse(string(tag)) | 	_, err := language.Parse(string(tag)) | ||||||
| 	return err == nil | 	return err == nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // NewURN generates an new valid IRI based on a UUID. It returns an IRI. | ||||||
|  | func NewURN() IRI { | ||||||
|  | 	return IRI(fmt.Sprint("urn:uuid:", uuid.New())) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // isValidXML checks whether a string is valid XML. It returns a bool. | ||||||
|  | func isValidXML(input string) bool { | ||||||
|  | 	var v interface{} | ||||||
|  | 	return xml.Unmarshal([]byte(input), &v) == nil | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										19
									
								
								category.go
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								category.go
									
									
									
									
									
								
							| @@ -8,17 +8,18 @@ import ( | |||||||
|  |  | ||||||
| type Category struct { | type Category struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	Content Content `xml:"content"` // undefinedContent in RFC4287 | 	Content string `xml:",chardata"` // undefinedContent in RFC4287 | ||||||
| 	Term    string `xml:"term,attr"` | 	Term    string `xml:"term,attr"` | ||||||
| 	Scheme  IRI    `xml:"scheme,attr,omitempty"` | 	Scheme  IRI    `xml:"scheme,attr,omitempty"` | ||||||
| 	Label   string `xml:"label,attr,omitempty"` | 	Label   string `xml:"label,attr,omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewCategory creates a new Category. It returns a *Category and an error. | // NewCategory creates a new Category. It returns a *Category and an error. | ||||||
| func NewCategory(term string) (*Category, error) { | func NewCategory(term, content string) (*Category, error) { | ||||||
| 	content, err := NewContent(InlineText, "", "") | 	if content != "" { | ||||||
| 	if err != nil { | 		if !isValidXML(content) { | ||||||
| 		return nil, fmt.Errorf("error creating content element: %v", err) | 			return nil, fmt.Errorf("%v not valid XML", content) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &Category{Term: term, Content: content}, nil | 	return &Category{Term: term, Content: content}, nil | ||||||
| @@ -46,11 +47,9 @@ func (c *Category) Check() error { | |||||||
| 		return fmt.Errorf("label attribute %v of category not correctly escaped", c.Label) | 		return fmt.Errorf("label attribute %v of category not correctly escaped", c.Label) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if c.Content == nil { | 	if c.Content != "" { | ||||||
| 		return errors.New("no content element of category") | 		if !isValidXML(c.Content) { | ||||||
| 	} else { | 			return fmt.Errorf("content element %v of category not valid XML", c.Content) | ||||||
| 		if err := c.Content.Check(); err != nil { |  | ||||||
| 			return fmt.Errorf("content element of category: %v", err) |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								date.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								date.go
									
									
									
									
									
								
							| @@ -7,7 +7,7 @@ import ( | |||||||
|  |  | ||||||
| type Date struct { | type Date struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	DateTime string | 	DateTime string `xml:",chardata"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // DateTime formats a time.Time to string formated as defined by RFC3339. It | // DateTime formats a time.Time to string formated as defined by RFC3339. It | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								entry.go
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								entry.go
									
									
									
									
									
								
							| @@ -34,11 +34,16 @@ type Entry struct { | |||||||
| // 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 | ||||||
| // atom:author element itself. | // atom:author element itself. | ||||||
| func (e *Entry) checkAuthors() error { | func (e *Entry) checkAuthors(authorInFeed bool) error { | ||||||
| 	if e.Authors == nil { | 	if e.Authors == nil { | ||||||
|  | 		if !authorInFeed { | ||||||
|  | 			if e.Source == nil { | ||||||
|  | 				return errors.New("no authors set in entry") | ||||||
|  | 			} | ||||||
| 			if e.Source.Authors == nil { | 			if e.Source.Authors == nil { | ||||||
| 				return errors.New("no authors set in entry") | 				return errors.New("no authors set in entry") | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		for i, a := range e.Authors { | 		for i, a := range e.Authors { | ||||||
| 			if err := a.Check(); err != nil { | 			if err := a.Check(); err != nil { | ||||||
| @@ -58,7 +63,7 @@ func NewEntry(title string) (*Entry, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &Entry{ | 	return &Entry{ | ||||||
| 		ID:      NewID(), | 		ID:      NewID(NewURN()), | ||||||
| 		Title:   text, | 		Title:   text, | ||||||
| 		Updated: NewDate(time.Now()), | 		Updated: NewDate(time.Now()), | ||||||
| 	}, nil | 	}, nil | ||||||
| @@ -135,7 +140,7 @@ func (e *Entry) Check() error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := e.checkAuthors(); err != nil { | 	if err := e.checkAuthors(true); err != nil { | ||||||
| 		return fmt.Errorf("entry %v: %v", e.ID.URI, err) | 		return fmt.Errorf("entry %v: %v", e.ID.URI, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -208,7 +213,7 @@ func (e *Entry) Check() error { | |||||||
| 		// is not an XML media type [RFC3023], does not begin with "text/", and | 		// is not an XML media type [RFC3023], does not begin with "text/", and | ||||||
| 		// does not end with "/xml" or "+xml". | 		// does not end with "/xml" or "+xml". | ||||||
| 		mediaType := e.Content.getType() | 		mediaType := e.Content.getType() | ||||||
| 		if !isXMLMediaType(mediaType) && !strings.HasPrefix(mediaType, "text/") { | 		if isValidMediaType(mediaType) && !isXMLMediaType(mediaType) && !strings.HasPrefix(mediaType, "text/") { | ||||||
| 			return fmt.Errorf("no summary element of entry %v but media type not xml", e.ID.URI) | 			return fmt.Errorf("no summary element of entry %v but media type not xml", e.ID.URI) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
							
								
								
									
										4
									
								
								feed.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								feed.go
									
									
									
									
									
								
							| @@ -34,7 +34,7 @@ func NewFeed(title string) (*Feed, error) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &Feed{ | 	return &Feed{ | ||||||
| 		ID:      NewID(), | 		ID:      NewID(NewURN()), | ||||||
| 		Title:   text, | 		Title:   text, | ||||||
| 		Updated: NewDate(time.Now()), | 		Updated: NewDate(time.Now()), | ||||||
| 	}, nil | 	}, nil | ||||||
| @@ -128,7 +128,7 @@ func (f *Feed) Check() error { | |||||||
| 	// least one atom:author element. | 	// least one atom:author element. | ||||||
| 	if f.Authors == nil { | 	if f.Authors == nil { | ||||||
| 		for _, e := range f.Entries { | 		for _, e := range f.Entries { | ||||||
| 			if err := e.checkAuthors(); err != nil { | 			if err := e.checkAuthors(false); err != nil { | ||||||
| 				return fmt.Errorf("no authors set in feed %v: %v", f.ID.URI, err) | 				return fmt.Errorf("no authors set in feed %v: %v", f.ID.URI, err) | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|   | |||||||
							
								
								
									
										8
									
								
								id.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								id.go
									
									
									
									
									
								
							| @@ -3,18 +3,16 @@ package atom | |||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  |  | ||||||
| 	"github.com/google/uuid" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type ID struct { | type ID struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	URI IRI `xml:"uri"` | 	URI IRI `xml:",chardata"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // NewID creates a new ID. It returns a *ID. | // NewID creates a new ID. It returns a *ID. | ||||||
| func NewID() *ID { | func NewID(id IRI) *ID { | ||||||
| 	return &ID{URI: IRI(fmt.Sprint("urn:uuid:", uuid.New()))} | 	return &ID{URI: IRI(id)} | ||||||
| } | } | ||||||
|  |  | ||||||
| // Check checks the ID for incompatibilities with RFC4287. It returns an error. | // Check checks the ID for incompatibilities with RFC4287. It returns an error. | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ import ( | |||||||
|  |  | ||||||
| type InlineOtherContent struct { | type InlineOtherContent struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	AnyElement any       `xml:"anyelement,omitempty"` | 	AnyElement any       `xml:",chardata"` | ||||||
| 	Type       MediaType `xml:"type,attr,omitempty"` | 	Type       MediaType `xml:"type,attr,omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,13 +3,12 @@ package atom | |||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"reflect" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type InlineTextContent struct { | type InlineTextContent struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	Type string `xml:"type,attr,omitempty"` // Must be text or html | 	Type string `xml:"type,attr,omitempty"` // Must be text or html | ||||||
| 	Texts []string `xml:"texts,omitempty"` | 	Text string `xml:",chardata"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // newInlineTextContent creates a new InlineTextContent. It returns a | // newInlineTextContent creates a new InlineTextContent. It returns a | ||||||
| @@ -19,23 +18,12 @@ func newInlineTextContent(mediaType string, content any) (*InlineTextContent, er | |||||||
| 		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) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	texts := make([]string, 0) | 	text, ok := content.(string) | ||||||
|  | 	if !ok { | ||||||
| 	t := reflect.TypeOf(content) |  | ||||||
| 	switch t.Kind() { |  | ||||||
| 	case reflect.Slice: |  | ||||||
| 		if t.Elem().Kind() == reflect.String { |  | ||||||
| 			for _, t := range content.([]string) { |  | ||||||
| 				texts = append(texts, t) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	case reflect.String: |  | ||||||
| 		texts = append(texts, content.(string)) |  | ||||||
| 	default: |  | ||||||
| 		return nil, fmt.Errorf("content type %T incompatible with inline text content", content) | 		return nil, fmt.Errorf("content type %T incompatible with inline text content", content) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &InlineTextContent{Type: mediaType, Texts: texts}, nil | 	return &InlineTextContent{Type: mediaType, Text: text}, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // isContent checks whether the InlineTextContent is a Content. It returns a | // isContent checks whether the InlineTextContent is a Content. It returns a | ||||||
|   | |||||||
| @@ -3,13 +3,12 @@ package atom | |||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"reflect" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type InlineXHTMLContent struct { | type InlineXHTMLContent struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	Type     string `xml:"type,attr"` | 	Type     string `xml:"type,attr"` | ||||||
| 	XHTMLDiv string `xml:"xhtmldiv"` | 	XHTMLDiv XHTMLDiv | ||||||
| } | } | ||||||
|  |  | ||||||
| // newInlineXHTMLContent creates a new InlineXHTMLContent. It returns a | // newInlineXHTMLContent creates a new InlineXHTMLContent. It returns a | ||||||
| @@ -19,11 +18,12 @@ func newInlineXHTMLContent(mediaType string, content any) (*InlineXHTMLContent, | |||||||
| 		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) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if reflect.TypeOf(content).Kind() != reflect.String { | 	xhtmlDiv, ok := content.(XHTMLDiv) | ||||||
|  | 	if !ok { | ||||||
| 		return nil, fmt.Errorf("content type %T incompatible with inline xhtml content", content) | 		return nil, fmt.Errorf("content type %T incompatible with inline xhtml content", content) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &InlineXHTMLContent{Type: mediaType, XHTMLDiv: content.(string)}, nil | 	return &InlineXHTMLContent{Type: mediaType, XHTMLDiv: xhtmlDiv}, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // isContent checks whether the InlineXHTMLContent is a Content. It returns a | // isContent checks whether the InlineXHTMLContent is a Content. It returns a | ||||||
| @@ -44,8 +44,8 @@ func (i *InlineXHTMLContent) Check() error { | |||||||
| 		return errors.New("type attribute of inline xhtml content must be xhtml") | 		return errors.New("type attribute of inline xhtml content must be xhtml") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if i.XHTMLDiv == "" { | 	if err := i.XHTMLDiv.Check(); err != nil { | ||||||
| 		return errors.New("xhtmlDiv element of inline xhtml content empty") | 		return fmt.Errorf("xhtml div element %v of inline xhtml content %v: %v", i.XHTMLDiv, i, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								link.go
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								link.go
									
									
									
									
									
								
							| @@ -9,7 +9,7 @@ import ( | |||||||
| type Link struct { | type Link struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	Title    string      `xml:"title,attr,omitempty"` | 	Title    string      `xml:"title,attr,omitempty"` | ||||||
| 	Content  Content     `xml:"content"` // undefinedContent in RFC4287 | 	Content  string      `xml:",chardata"` // undefinedContent in RFC4287 | ||||||
| 	Href     IRI         `xml:"href,attr"` | 	Href     IRI         `xml:"href,attr"` | ||||||
| 	Rel      string      `xml:"rel,attr,omitempty"` | 	Rel      string      `xml:"rel,attr,omitempty"` | ||||||
| 	Type     MediaType   `xml:"type,attr,omitempty"` | 	Type     MediaType   `xml:"type,attr,omitempty"` | ||||||
| @@ -18,10 +18,11 @@ type Link struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // NewLink creates a new Link. It returns a *Link and an error. | // NewLink creates a new Link. It returns a *Link and an error. | ||||||
| func NewLink(href string) (*Link, error) { | func NewLink(href, content string) (*Link, error) { | ||||||
| 	content, err := NewContent(InlineText, "", "") | 	if content != "" { | ||||||
| 	if err != nil { | 		if !isValidXML(content) { | ||||||
| 		return nil, fmt.Errorf("error creating content element: %v", err) | 			return nil, fmt.Errorf("%v not valid XML", content) | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &Link{Href: IRI(href), Content: content}, nil | 	return &Link{Href: IRI(href), Content: content}, nil | ||||||
| @@ -38,23 +39,27 @@ func (l *Link) Check() error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if strings.Contains(l.Rel, ":") || !isValidIRI(IRI(l.Rel)) { | 	if l.Rel != "" { | ||||||
|  | 		if strings.Contains(l.Rel, ":") && !isValidIRI(IRI(l.Rel)) { | ||||||
| 			return fmt.Errorf("rel attribute %v of link %v not correctly formatted", l.Rel, l.Href) | 			return fmt.Errorf("rel attribute %v of link %v not correctly formatted", l.Rel, l.Href) | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if l.Type != "" { | ||||||
| 		if !isValidMediaType(string(l.Type)) { | 		if !isValidMediaType(string(l.Type)) { | ||||||
| 			return fmt.Errorf("type attribute %v of link %v invalid media type", l.Type, l.Href) | 			return fmt.Errorf("type attribute %v of link %v invalid media type", l.Type, l.Href) | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if l.HrefLang != "" { | ||||||
| 		if !isValidLanguageTag(l.HrefLang) { | 		if !isValidLanguageTag(l.HrefLang) { | ||||||
| 			return fmt.Errorf("hreflang attribute %v of link %v invalid language tag", l.Type, l.HrefLang) | 			return fmt.Errorf("hreflang attribute %v of link %v invalid language tag", l.Type, l.HrefLang) | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if l.Content == nil { | 	if l.Content != "" { | ||||||
| 		return fmt.Errorf("no content element of link %v", l.Href) | 		if !isValidXML(l.Content) { | ||||||
| 	} else { | 			return fmt.Errorf("content element %v of link not valid XML", l.Content) | ||||||
| 		if err := l.Content.Check(); err != nil { |  | ||||||
| 			return fmt.Errorf("content element of link %v: %v", l.Href, err) |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ import ( | |||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"mime" | 	"mime" | ||||||
| 	"reflect" |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type OutOfLineContent struct { | type OutOfLineContent struct { | ||||||
| @@ -20,15 +19,16 @@ func newOutOfLineContent(mediaType string, content any) (*OutOfLineContent, erro | |||||||
| 		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) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if reflect.TypeOf(content).Kind() != reflect.String { | 	iri, ok := content.(IRI) | ||||||
|  | 	if !ok { | ||||||
| 		return nil, fmt.Errorf("content type %T incompatible with out of line content", content) | 		return nil, fmt.Errorf("content type %T incompatible with out of line content", content) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !isValidIRI(content.(IRI)) { | 	if !isValidIRI(iri) { | ||||||
| 		return nil, errors.New("content not a valid uri") | 		return nil, errors.New("content not a valid uri") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &OutOfLineContent{Type: MediaType(mediaType), SRC: content.(IRI)}, nil | 	return &OutOfLineContent{Type: MediaType(mediaType), SRC: iri}, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // isContent checks whether the OutOfLineContent is a Content. It returns a | // isContent checks whether the OutOfLineContent is a Content. It returns a | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import "errors" | |||||||
| type PlainText struct { | type PlainText struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	Type string `xml:"type,attr,omitempty"` // Must be text or html | 	Type string `xml:"type,attr,omitempty"` // Must be text or html | ||||||
| 	Text string `xml:"text"` | 	Text string `xml:",chardata"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // isText checks whether the PlainText is a Text. It returns a bool. | // isText checks whether the PlainText is a Text. It returns a bool. | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								xhtmlDiv.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								xhtmlDiv.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | package atom | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"encoding/xml" | ||||||
|  | 	"errors" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type XHTMLDiv struct { | ||||||
|  | 	XMLName xml.Name `xml:"div"` | ||||||
|  | 	XMLNS   string   `xml:"xmlns,attr"` | ||||||
|  | 	Content string   `xml:",innerxml"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // NewXHTMLDiv creates a new XHTMLDiv. It returns a *XHTMLDiv. | ||||||
|  | func NewXHTMLDiv(content string) *XHTMLDiv { | ||||||
|  | 	return &XHTMLDiv{ | ||||||
|  | 		XMLNS:   "http://www.w3.org/1999/xhtml", | ||||||
|  | 		Content: content, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Check checks the XHTMLDiv for incompatibilities with RFC4287. It returns an | ||||||
|  | // error. | ||||||
|  | func (x *XHTMLDiv) Check() error { | ||||||
|  | 	if x.XMLNS != "http://www.w3.org/1999/xhtml" { | ||||||
|  | 		return errors.New("xmlns attribute of xhtml text must be http://www.w3.org/1999/xhtml") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										12
									
								
								xhtmlText.go
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								xhtmlText.go
									
									
									
									
									
								
							| @@ -1,16 +1,10 @@ | |||||||
| package atom | package atom | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"encoding/xml" |  | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"fmt" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| type XHTMLDiv struct { |  | ||||||
| 	XMLName xml.Name `xml:"div"` |  | ||||||
| 	XMLNS   string   `xml:"xmlns,attr"` |  | ||||||
| 	Content string   `xml:",innerxml"` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| type XHTMLText struct { | type XHTMLText struct { | ||||||
| 	*CommonAttributes | 	*CommonAttributes | ||||||
| 	Type     string `xml:"type,attr"` // Must be xhtml | 	Type     string `xml:"type,attr"` // Must be xhtml | ||||||
| @@ -27,8 +21,8 @@ func (x *XHTMLText) Check() error { | |||||||
| 		return errors.New("type attribute of xhtml text must be xhtml") | 		return errors.New("type attribute of xhtml text must be xhtml") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if x.XHTMLDiv.XMLNS != "http://www.w3.org/1999/xhtml" { | 	if err := x.XHTMLDiv.Check(); err != nil { | ||||||
| 		return errors.New("xmlns attribute of xhtml text must be http://www.w3.org/1999/xhtml") | 		return fmt.Errorf("xhtml div element %v of xhtml text %v: %v", x.XHTMLDiv, x, err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user