diff --git a/pkg/message/message_element.go b/pkg/message/message_element.go
index 96baac4..ce3d4ec 100644
--- a/pkg/message/message_element.go
+++ b/pkg/message/message_element.go
@@ -1,5 +1,9 @@
package message
+import (
+ "golang.org/x/net/html"
+)
+
type MessageElement interface {
Tag() string
Stringify() string
@@ -31,9 +35,54 @@ func (e *ChildrenMessageElement) stringifyChildren() string {
return result
}
-func (e *ChildrenMessageElement) stringifyByTag(tag string) string {
- if e == nil || len(e.Children) == 0 {
- return "<" + tag + " />"
+func (e *ChildrenMessageElement) parseChildren(n *html.Node) (*ChildrenMessageElement, error) {
+ var children []MessageElement
+ err := parseHtmlChildrenNode(n, func(e MessageElement) {
+ children = append(children, e)
+ })
+ if err != nil {
+ return nil, err
+ }
+ result := &ChildrenMessageElement{
+ Children: children,
+ }
+ return result, nil
+}
+
+type ExtendAttributes struct {
+ Attributes map[string]string
+}
+
+func (e *ExtendAttributes) AddAttribute(key, value string) *ExtendAttributes {
+ result := e
+ if result == nil {
+ result = &ExtendAttributes{
+ Attributes: make(map[string]string),
+ }
}
- return "<" + tag + ">" + e.stringifyChildren() + "" + tag + ">"
+ result.Attributes[key] = value
+ return result
+}
+
+func (e *ExtendAttributes) Get(key string) (string, bool) {
+ if e == nil {
+ return "", false
+ }
+ v, ok := e.Attributes[key]
+ return v, ok
+}
+
+func (e *ExtendAttributes) stringifyAttributes() string {
+ if e == nil || len(e.Attributes) == 0 {
+ return ""
+ }
+ var result string
+ for k, v := range e.Attributes {
+ if v == "" {
+ result += " " + k
+ } else {
+ result += " " + k + `="` + escape(v, true) + `"`
+ }
+ }
+ return result
}
diff --git a/pkg/message/message_element_basic.go b/pkg/message/message_element_basic.go
index f494177..a0717b3 100644
--- a/pkg/message/message_element_basic.go
+++ b/pkg/message/message_element_basic.go
@@ -33,6 +33,8 @@ func (e *MessageElementText) Parse(n *html.Node) (MessageElement, error) {
type MessageElementAt struct {
*noAliasMessageElement
+ *ChildrenMessageElement
+ *ExtendAttributes
Id string
Name string // 收发 目标用户的名称
Role string // 收发 目标角色
@@ -44,7 +46,7 @@ func (e *MessageElementAt) Tag() string {
}
func (e *MessageElementAt) Stringify() string {
- result := "<" + e.Tag()
+ result := ""
if e.Id != "" {
result += ` id="` + escape(e.Id, true) + `"`
}
@@ -57,21 +59,39 @@ func (e *MessageElementAt) Stringify() string {
if e.Type != "" {
result += ` type="` + escape(e.Type, true) + `"`
}
- return result + "/>"
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementAt) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
- return &MessageElementAt{
+ result := &MessageElementAt{
Id: attrMap["id"],
Name: attrMap["name"],
Role: attrMap["role"],
Type: attrMap["type"],
- }, nil
+ }
+ for key, value := range attrMap {
+ if key != "id" && key != "name" && key != "role" && key != "type" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementSharp struct {
*noAliasMessageElement
+ *ChildrenMessageElement
+ *ExtendAttributes
Id string //收发 目标频道的 ID
Name string //收发 目标频道的名称
}
@@ -81,26 +101,44 @@ func (e *MessageElementSharp) Tag() string {
}
func (e *MessageElementSharp) Stringify() string {
- result := "<" + e.Tag()
+ result := ""
if e.Id != "" {
result += ` id="` + escape(e.Id, true) + `"`
}
if e.Name != "" {
result += ` name="` + escape(e.Name, true) + `"`
}
- return result + "/>"
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementSharp) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
- return &MessageElementSharp{
+ result := &MessageElementSharp{
Id: attrMap["id"],
Name: attrMap["name"],
- }, nil
+ }
+ for key, value := range attrMap {
+ if key != "id" && key != "name" && key != "role" && key != "type" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementA struct {
*noAliasMessageElement
+ *ChildrenMessageElement
+ *ExtendAttributes
Href string
}
@@ -109,17 +147,33 @@ func (e *MessageElementA) Tag() string {
}
func (e *MessageElementA) Stringify() string {
- result := "<" + e.Tag()
+ result := ""
if e.Href != "" {
result += ` href="` + escape(e.Href, true) + `"`
}
- return result + "/>"
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementA) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
- return &MessageElementA{
+ result := &MessageElementA{
Href: attrMap["href"],
- }, nil
+ }
+ for key, value := range attrMap {
+ if key != "href" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
+ return result, nil
}
func init() {
diff --git a/pkg/message/message_element_decorative.go b/pkg/message/message_element_decorative.go
index ff23843..bdbb0dc 100644
--- a/pkg/message/message_element_decorative.go
+++ b/pkg/message/message_element_decorative.go
@@ -6,6 +6,7 @@ import (
type MessageElementStrong struct {
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElementStrong) Tag() string {
@@ -16,26 +17,31 @@ func (e *MessageElementStrong) Alias() []string {
}
func (e *MessageElementStrong) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementStrong) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementStrong{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementStrong{
- &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementEm struct {
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElementEm) Tag() string {
@@ -46,26 +52,31 @@ func (e *MessageElementEm) Alias() []string {
}
func (e *MessageElementEm) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementEm) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementEm{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementEm{
- &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementIns struct {
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElementIns) Tag() string {
@@ -77,26 +88,31 @@ func (e *MessageElementIns) Alias() []string {
}
func (e *MessageElementIns) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementIns) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementIns{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementIns{
- &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementDel struct {
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElementDel) Tag() string {
@@ -108,27 +124,32 @@ func (e *MessageElementDel) Alias() []string {
}
func (e *MessageElementDel) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementDel) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementDel{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementDel{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementSpl struct {
*noAliasMessageElement
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElementSpl) Tag() string {
@@ -136,27 +157,32 @@ func (e *MessageElementSpl) Tag() string {
}
func (e *MessageElementSpl) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementSpl) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementSpl{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementSpl{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementCode struct {
*ChildrenMessageElement
*noAliasMessageElement
+ *ExtendAttributes
}
func (e *MessageElementCode) Tag() string {
@@ -164,27 +190,32 @@ func (e *MessageElementCode) Tag() string {
}
func (e *MessageElementCode) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementCode) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementCode{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementCode{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementSup struct {
*ChildrenMessageElement
*noAliasMessageElement
+ *ExtendAttributes
}
func (e *MessageElementSup) Tag() string {
@@ -192,27 +223,32 @@ func (e *MessageElementSup) Tag() string {
}
func (e *MessageElementSup) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementSup) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementSup{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementSup{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementSub struct {
*ChildrenMessageElement
*noAliasMessageElement
+ *ExtendAttributes
}
func (e *MessageElementSub) Tag() string {
@@ -220,22 +256,26 @@ func (e *MessageElementSub) Tag() string {
}
func (e *MessageElementSub) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementSub) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementSub{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementSub{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
func init() {
diff --git a/pkg/message/message_element_meta.go b/pkg/message/message_element_meta.go
index 8c7c897..9d2ac38 100644
--- a/pkg/message/message_element_meta.go
+++ b/pkg/message/message_element_meta.go
@@ -5,6 +5,7 @@ import "golang.org/x/net/html"
type MessageElementQuote struct {
*noAliasMessageElement
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElementQuote) Tag() string {
@@ -12,27 +13,32 @@ func (e *MessageElementQuote) Tag() string {
}
func (e *MessageElementQuote) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementQuote) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElementQuote{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElementQuote{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementAuthor struct {
*noAliasMessageElement
*ChildrenMessageElement
+ *ExtendAttributes
Id string
Name string
Avatar string
@@ -43,7 +49,7 @@ func (e *MessageElementAuthor) Tag() string {
}
func (e *MessageElementAuthor) Stringify() string {
- result := "<" + e.Tag()
+ result := ""
if e.Id != "" {
result += ` id="` + escape(e.Id, true) + `"`
}
@@ -53,12 +59,12 @@ func (e *MessageElementAuthor) Stringify() string {
if e.Avatar != "" {
result += ` avatar="` + escape(e.Avatar, true) + `"`
}
- // result += ">"
+ result += e.stringifyAttributes()
childrenStr := e.stringifyChildren()
if childrenStr == "" {
- return result + `/>`
+ return `<` + e.Tag() + result + `/>`
}
- return result + `>` + childrenStr + `` + e.Tag() + `>`
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementAuthor) Parse(n *html.Node) (MessageElement, error) {
@@ -68,12 +74,16 @@ func (e *MessageElementAuthor) Parse(n *html.Node) (MessageElement, error) {
Name: attrMap["name"],
Avatar: attrMap["avatar"],
}
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- result.Children = append(result.Children, e)
- })
+ for key, value := range attrMap {
+ if key != "id" && key != "name" && key != "avatar" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
+ result.ChildrenMessageElement = children
return result, nil
}
func init() {
diff --git a/pkg/message/message_element_oprator.go b/pkg/message/message_element_oprator.go
index 515df30..0844967 100644
--- a/pkg/message/message_element_oprator.go
+++ b/pkg/message/message_element_oprator.go
@@ -4,6 +4,8 @@ import "golang.org/x/net/html"
type MessageElementButton struct {
*noAliasMessageElement
+ *ChildrenMessageElement
+ *ExtendAttributes
// id string? 发 按钮的 ID
//
// type string? 发 按钮的类型
@@ -22,7 +24,7 @@ func (e *MessageElementButton) Tag() string {
}
func (e *MessageElementButton) Stringify() string {
- result := "<" + e.Tag()
+ result := ""
if e.Id != "" {
result += ` id="` + escape(e.Id, true) + `"`
}
@@ -38,18 +40,34 @@ func (e *MessageElementButton) Stringify() string {
if e.Theme != "" {
result += ` theme="` + escape(e.Theme, true) + `"`
}
- return result + "/>"
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementButton) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
- return &MessageElementButton{
+ result := &MessageElementButton{
Id: attrMap["id"],
Type: attrMap["type"],
Href: attrMap["href"],
Text: attrMap["text"],
Theme: attrMap["theme"],
- }, nil
+ }
+ for key, value := range attrMap {
+ if key != "id" && key != "type" && key != "href" && key != "text" && key != "theme" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
+ return result, nil
}
func init() {
diff --git a/pkg/message/message_element_resource.go b/pkg/message/message_element_resource.go
index 680ef74..494bcb4 100644
--- a/pkg/message/message_element_resource.go
+++ b/pkg/message/message_element_resource.go
@@ -44,12 +44,15 @@ import (
// }
// func (e *ResourceRootMessageElement) stringifyByTag(tag string) string {
-// return "<" + tag + e.attrString() + " />"
+// return "<" + tag + e.attrString() + "/>"
// }
type MessageElementImg struct {
*noAliasMessageElement
+ *ChildrenMessageElement
+ *ExtendAttributes
Src string
+ Title string
Cache bool
Timeout string //ms
Width uint32
@@ -68,6 +71,9 @@ func (e *MessageElementImg) attrString() string {
if e.Src != "" {
result += ` src="` + escape(e.Src, true) + `"`
}
+ if e.Title != "" {
+ result += ` title="` + escape(e.Title, true) + `"`
+ }
if e.Cache {
result += ` cache`
}
@@ -78,22 +84,28 @@ func (e *MessageElementImg) attrString() string {
}
func (e *MessageElementImg) Stringify() string {
- result := "<" + e.Tag()
+ result := ""
attrStr := e.attrString()
if e.Width > 0 {
- attrStr += fmt.Sprintf(" width=%d", e.Width)
+ attrStr += fmt.Sprintf(` width="%d"`, e.Width)
}
if e.Height > 0 {
- attrStr += fmt.Sprintf(" height=%d", e.Height)
+ attrStr += fmt.Sprintf(` height="%d"`, e.Height)
}
result += attrStr
- return result + " />"
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementImg) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
result := &MessageElementImg{
Src: attrMap["src"],
+ Title: attrMap["title"],
Cache: false,
Timeout: attrMap["timeout"],
}
@@ -115,14 +127,29 @@ func (e *MessageElementImg) Parse(n *html.Node) (MessageElement, error) {
}
result.Height = uint32(height)
}
+ for key, value := range attrMap {
+ if key != "src" && key != "title" && key != "cache" && key != "timeout" && key != "width" && key != "height" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
return result, nil
}
type MessageElementAudio struct {
*noAliasMessageElement
- Src string
- Cache bool
- Timeout string //ms
+ *ChildrenMessageElement
+ *ExtendAttributes
+ Src string
+ Title string
+ Cache bool
+ Timeout string //ms
+ Duration uint32
+ Poster string
}
func (e *MessageElementAudio) Tag() string {
@@ -137,6 +164,9 @@ func (e *MessageElementAudio) attrString() string {
if e.Src != "" {
result += ` src="` + escape(e.Src, true) + `"`
}
+ if e.Title != "" {
+ result += ` title="` + escape(e.Title, true) + `"`
+ }
if e.Cache {
result += ` cache`
}
@@ -147,15 +177,29 @@ func (e *MessageElementAudio) attrString() string {
}
func (e *MessageElementAudio) Stringify() string {
- result := "<" + e.Tag()
- result += e.attrString()
- return result + " />"
+ result := ""
+ attrStr := e.attrString()
+ if e.Duration > 0 {
+ attrStr += fmt.Sprintf(` duration="%d"`, e.Duration)
+
+ }
+ if e.Poster != "" {
+ attrStr += ` poster="` + escape(e.Poster, true) + `"`
+ }
+ result += attrStr
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementAudio) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
result := &MessageElementAudio{
Src: attrMap["src"],
+ Title: attrMap["title"],
Cache: false,
Timeout: attrMap["timeout"],
}
@@ -163,14 +207,41 @@ func (e *MessageElementAudio) Parse(n *html.Node) (MessageElement, error) {
if ok {
result.Cache = cacheAttr == "" || cacheAttr == "true" || cacheAttr == "1"
}
+ if d, ok := attrMap["duration"]; ok {
+ duration, e := strconv.Atoi(d)
+ if e != nil {
+ return nil, fmt.Errorf("duration[%s] is illegal:%v", d, e)
+ }
+ result.Duration = uint32(duration)
+ }
+ if p, ok := attrMap["poster"]; ok {
+ result.Poster = p
+ }
+ for key, value := range attrMap {
+ if key != "src" && key != "title" && key != "cache" && key != "timeout" && key != "duration" && key != "poster" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
return result, nil
}
type MessageElementVideo struct {
*noAliasMessageElement
- Src string
- Cache bool
- Timeout string //ms
+ *ChildrenMessageElement
+ *ExtendAttributes
+ Src string
+ Title string
+ Cache bool
+ Timeout string //ms
+ Width uint32
+ Height uint32
+ Duration uint32
+ Poster string
}
func (e *MessageElementVideo) Tag() string {
@@ -185,6 +256,9 @@ func (e *MessageElementVideo) attrString() string {
if e.Src != "" {
result += ` src="` + escape(e.Src, true) + `"`
}
+ if e.Title != "" {
+ result += ` title="` + escape(e.Title, true) + `"`
+ }
if e.Cache {
result += ` cache`
}
@@ -195,15 +269,34 @@ func (e *MessageElementVideo) attrString() string {
}
func (e *MessageElementVideo) Stringify() string {
- result := "<" + e.Tag()
- result += e.attrString()
- return result + " />"
+ result := ""
+ attrStr := e.attrString()
+ if e.Width > 0 {
+ attrStr += fmt.Sprintf(` width="%d"`, e.Width)
+ }
+ if e.Height > 0 {
+ attrStr += fmt.Sprintf(` height="%d"`, e.Height)
+ }
+ if e.Duration > 0 {
+ attrStr += fmt.Sprintf(` duration="%d"`, e.Duration)
+ }
+ if e.Poster != "" {
+ attrStr += ` poster="` + escape(e.Poster, true) + `"`
+ }
+ result += attrStr
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementVideo) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
result := &MessageElementVideo{
Src: attrMap["src"],
+ Title: attrMap["title"],
Cache: false,
Timeout: attrMap["timeout"],
}
@@ -211,14 +304,52 @@ func (e *MessageElementVideo) Parse(n *html.Node) (MessageElement, error) {
if ok {
result.Cache = cacheAttr == "" || cacheAttr == "true" || cacheAttr == "1"
}
+ if w, ok := attrMap["width"]; ok {
+ width, e := strconv.Atoi(w)
+ if e != nil {
+ return nil, fmt.Errorf("width[%s] is illegal:%v", w, e)
+ }
+ result.Width = uint32(width)
+ }
+ if h, ok := attrMap["height"]; ok {
+ height, e := strconv.Atoi(h)
+ if e != nil {
+ return nil, fmt.Errorf("height[%s] is illegal:%v", h, e)
+ }
+ result.Height = uint32(height)
+ }
+ if d, ok := attrMap["duration"]; ok {
+ duration, e := strconv.Atoi(d)
+ if e != nil {
+ return nil, fmt.Errorf("duration[%s] is illegal:%v", d, e)
+ }
+ result.Duration = uint32(duration)
+ }
+ if p, ok := attrMap["poster"]; ok {
+ result.Poster = p
+ }
+ for key, value := range attrMap {
+ if key != "src" && key != "title" && key != "cache" && key != "timeout" && key != "width" && key != "height" && key != "duration" && key != "poster" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
return result, nil
}
type MessageElementFile struct {
*noAliasMessageElement
+ *ChildrenMessageElement
+ *ExtendAttributes
Src string
+ Title string
Cache bool
Timeout string //ms
+ Poster string
}
func (e *MessageElementFile) Tag() string {
@@ -232,6 +363,9 @@ func (e *MessageElementFile) attrString() string {
if e.Src != "" {
result += ` src="` + escape(e.Src, true) + `"`
}
+ if e.Title != "" {
+ result += ` title="` + escape(e.Title, true) + `"`
+ }
if e.Cache {
result += ` cache`
}
@@ -241,15 +375,25 @@ func (e *MessageElementFile) attrString() string {
return result
}
func (e *MessageElementFile) Stringify() string {
- result := "<" + e.Tag()
- result += e.attrString()
- return result + " />"
+ result := ""
+ attrStr := e.attrString()
+ if e.Poster != "" {
+ attrStr += ` poster="` + escape(e.Poster, true) + `"`
+ }
+ result += attrStr
+ result += e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return `<` + e.Tag() + result + `/>`
+ }
+ return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
}
func (e *MessageElementFile) Parse(n *html.Node) (MessageElement, error) {
attrMap := attrList2MapVal(n.Attr)
result := &MessageElementFile{
Src: attrMap["src"],
+ Title: attrMap["title"],
Cache: false,
Timeout: attrMap["timeout"],
}
@@ -257,6 +401,19 @@ func (e *MessageElementFile) Parse(n *html.Node) (MessageElement, error) {
if ok {
result.Cache = cacheAttr == "" || cacheAttr == "true" || cacheAttr == "1"
}
+ if p, ok := attrMap["poster"]; ok {
+ result.Poster = p
+ }
+ for key, value := range attrMap {
+ if key != "src" && key != "title" && key != "cache" && key != "timeout" && key != "poster" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
return result, nil
}
diff --git a/pkg/message/message_element_typography.go b/pkg/message/message_element_typography.go
index 4559f14..7cdfce4 100644
--- a/pkg/message/message_element_typography.go
+++ b/pkg/message/message_element_typography.go
@@ -23,6 +23,7 @@ func (e *MessageElmentBr) Parse(n *html.Node) (MessageElement, error) {
type MessageElmentP struct {
*noAliasMessageElement
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElmentP) Tag() string {
@@ -30,22 +31,26 @@ func (e *MessageElmentP) Tag() string {
}
func (e *MessageElmentP) Stringify() string {
- return e.stringifyByTag(e.Tag())
+ result := e.stringifyAttributes()
+ childrenStr := e.stringifyChildren()
+ if childrenStr == "" {
+ return "<" + e.Tag() + result + "/>"
+ }
+ return "<" + e.Tag() + result + ">" + childrenStr + "" + e.Tag() + ">"
}
func (e *MessageElmentP) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
+ attrMap := attrList2MapVal(n.Attr)
+ result := &MessageElmentP{}
+ for key, value := range attrMap {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ children, err := result.parseChildren(n)
if err != nil {
return nil, err
}
- return &MessageElmentP{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
- }, nil
+ result.ChildrenMessageElement = children
+ return result, nil
}
type MessageElementMessage struct {
@@ -53,6 +58,7 @@ type MessageElementMessage struct {
Forward bool
*noAliasMessageElement
*ChildrenMessageElement
+ *ExtendAttributes
}
func (e *MessageElementMessage) Tag() string {
@@ -67,27 +73,18 @@ func (e *MessageElementMessage) Stringify() string {
if e.Forward {
result += ` forward`
}
+ result += e.stringifyAttributes()
childrenStr := e.stringifyChildren()
if childrenStr == "" {
- return `<` + e.Tag() + result + ` />`
+ return "<" + e.Tag() + result + "/>"
}
- return `<` + e.Tag() + result + `>` + childrenStr + `` + e.Tag() + `>`
+ return "<" + e.Tag() + result + ">" + childrenStr + "" + e.Tag() + ">"
}
func (e *MessageElementMessage) Parse(n *html.Node) (MessageElement, error) {
- var children []MessageElement
- err := parseHtmlChildrenNode(n, func(e MessageElement) {
- children = append(children, e)
- })
- if err != nil {
- return nil, err
- }
attrMap := attrList2MapVal(n.Attr)
result := &MessageElementMessage{
Forward: false,
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: children,
- },
}
if id, ok := attrMap["id"]; ok {
result.Id = id
@@ -95,6 +92,16 @@ func (e *MessageElementMessage) Parse(n *html.Node) (MessageElement, error) {
if forwardAttr, ok := attrMap["forward"]; ok {
result.Forward = forwardAttr == "" || forwardAttr == "true" || forwardAttr == "1"
}
+ for key, value := range attrMap {
+ if key != "id" && key != "forward" {
+ result.ExtendAttributes = result.AddAttribute(key, value)
+ }
+ }
+ children, err := result.parseChildren(n)
+ if err != nil {
+ return nil, err
+ }
+ result.ChildrenMessageElement = children
return result, nil
}
diff --git a/pkg/message/parser.go b/pkg/message/parser.go
index 182d65e..7fdd416 100644
--- a/pkg/message/parser.go
+++ b/pkg/message/parser.go
@@ -1,7 +1,6 @@
package message
import (
- "fmt"
"strings"
"golang.org/x/net/html"
@@ -41,7 +40,6 @@ var factory = &parsersStruct{
}
func RegsiterParserElement(parser MessageElementParser) {
- fmt.Printf("set parser tag:[%s],with alias: %v\n", parser.Tag(), parser.Alias())
factory.set(parser.Tag(), parser.Parse)
if len(parser.Alias()) > 0 {
for _, tag := range parser.Alias() {
diff --git a/pkg/message/parser_test.go b/pkg/message/parser_test.go
index 37594e8..7207646 100644
--- a/pkg/message/parser_test.go
+++ b/pkg/message/parser_test.go
@@ -8,20 +8,16 @@ func Test(t *testing.T) {
for group, messages := range _getRawMessage() {
t.Logf("start test group: %s", group)
for _, message := range messages {
- _, err := Parse(message.Raw)
+ elements, err := Parse(message)
if err != nil {
- t.Fatalf("%s Parse error: %s", message.Raw, err)
+ t.Fatalf("%s Parse error: %s", message, err)
}
- result, err := Stringify(message.Elements)
+ result, err := Stringify(elements)
if err != nil {
- t.Fatalf("%s Stringify error: %s", message.Elements, err)
+ t.Fatalf("%s Stringify error: %s", elements, err)
}
- if message.TargetRaw != "" {
- if result != message.TargetRaw {
- t.Fatalf("%s not eq %s", result, message.TargetRaw)
- }
- } else if result != message.Raw {
- t.Fatalf("%s not eq %s", result, message.Raw)
+ if result != message {
+ t.Fatalf("%s not eq %s", result, message)
}
}
}
diff --git a/pkg/message/parser_test_data.go b/pkg/message/parser_test_data.go
index 8d27e22..f472877 100644
--- a/pkg/message/parser_test_data.go
+++ b/pkg/message/parser_test_data.go
@@ -1,569 +1,72 @@
package message
-type rawToElement struct {
- Raw string
- TargetRaw string
- Elements []MessageElement
-}
-
-func _getRawMessage() map[string][]rawToElement {
- raw_message := make(map[string][]rawToElement)
- raw_message["Basic"] = _getBasicRawMessage()
- raw_message["Layout"] = _getLayoutRawMessage()
- raw_message["Meta"] = _getMetaRawMessage()
- raw_message["Resource"] = _getResourceRawMessage()
- raw_message["Modifier"] = _getModifierRawMessage()
- raw_message["Examples"] = _getExamplesRawMessage()
+func _getRawMessage() map[string][]string {
+ raw_message := make(map[string][]string)
+ raw_message["basic"] = _getBasicRawMessage()
+ raw_message["resource"] = _getResourceRawMessage()
+ raw_message["decorate"] = _getDecorateRawMessage()
+ raw_message["layout"] = _getLayoutRawMessage()
+ raw_message["meta"] = _getMetaRawMessage()
+ raw_message["interact"] = _getInteractRawMessage()
+ raw_message["extend"] = _getExtendRawMessage()
return raw_message
}
-func _getExamplesRawMessage() []rawToElement {
- return []rawToElement{
+func _getBasicRawMessage() []string {
+ return []string{
// Single message
- {
- Raw: `
- test
- bold
- sup
- sub
- test boldsupsub
-
-
-
code
- underline
- strikethrough
- code
underlinestrikethroughcode
- underline
- strikethrough
- */
- Children: []MessageElement{
- &MessageElementStrong{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{
- &MessageElementText{
- Content: "bold",
- },
- },
- },
- },
- &MessageElementSup{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{
- &MessageElementText{
- Content: "sup",
- },
- },
- },
- },
- &MessageElementSub{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{
- &MessageElementText{
- Content: "sub",
- },
- },
- },
- },
- &MessageElementSpl{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{
- &MessageElementText{
- Content: "spoiler",
- },
- },
- },
- },
- &MessageElementCode{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{
- &MessageElementText{
- Content: "code",
- },
- },
- },
- },
- &MessageElementIns{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{
- &MessageElementText{
- Content: "underline",
- },
- },
- },
- },
- &MessageElementDel{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{
- &MessageElementText{
- Content: "strikethrough",
- },
- },
- },
- },
- },
- },
- },
- },
- },
- },
- },
- },
- {Raw: `
- yarn add nitori
- yarn run test
- npm publish
-
-yarn add nitori\n yarn run test\n npm publish
`,
+ ``,
+ ``,
+ `
test`,
- TargetRaw: `test`,
- Elements: []MessageElement{&MessageElementDel{
- &ChildrenMessageElement{
- Children: []MessageElement{&MessageElementText{
- Content: "test",
- }},
- },
- }},
- },
- {
- Raw: `test`,
- Elements: []MessageElement{&MessageElementDel{
- &ChildrenMessageElement{
- Children: []MessageElement{&MessageElementText{
- Content: "test",
- }},
- },
- }},
- },
- {
- Raw: `test
`,
- Elements: []MessageElement{&MessageElementCode{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{&MessageElementText{
- Content: "test",
- }},
- },
- }},
- },
- {
- Raw: `test`,
- Elements: []MessageElement{&MessageElementSup{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{&MessageElementText{
- Content: "test",
- }},
- },
- }},
- },
- {
- Raw: `test`,
- Elements: []MessageElement{&MessageElementSub{
- ChildrenMessageElement: &ChildrenMessageElement{
- Children: []MessageElement{&MessageElementText{
- Content: "test",
- }},
- },
- }},
- },
+func _getDecorateRawMessage() []string {
+ return []string{
+ `bitalicounderdeletelinelinelcode
oissubuplerfor key, value range attributes {
+ fmt.Println(key, value)
+ }
`,
}
}
-func _getResourceRawMessage() []rawToElement {
- return []rawToElement{
- {
- Raw: ``,
- Elements: []MessageElement{
- &MessageElementImg{
- Src: "https://example.com",
- },
- },
- },
- {
- Raw: `
`,
- Elements: []MessageElement{
- &MessageElementImg{
- Src: "https://example.com",
- Cache: true,
- Timeout: "1000",
- }},
- },
- {
- Raw: `
`,
- TargetRaw: `
`,
- Elements: []MessageElement{&MessageElementImg{
- Src: "https://example.com",
- Width: 300,
- Height: 200,
- }},
- },
- {
- Raw: ``,
- Elements: []MessageElement{&MessageElementAudio{
- Src: "https://example.com",
- }},
- },
- {
- Raw: ``,
- Elements: []MessageElement{&MessageElementVideo{
- Src: "https://example.com",
- }},
- },
- {
- Raw: `
`,
+ `
test
`, + `test
testtest
`, - Elements: []MessageElement{&MessageElementQuote{}}, - }, - { - Raw: `
test`, - Elements: []MessageElement{&MessageElementQuote{ - ChildrenMessageElement: &ChildrenMessageElement{ - Children: []MessageElement{ - &MessageElementText{ - Content: "test", - }, - }, - }, - }}, - }, - { - Raw: `
`, + `test test
test
`, - Elements: []MessageElement{ - &MessageElmentP{ - ChildrenMessageElement: &ChildrenMessageElement{ - Children: []MessageElement{ - &MessageElementText{ - Content: "test", - }, - }, - }, - }, - }, - }, - { - Raw: `testtest2
`, - Elements: []MessageElement{ - &MessageElmentP{ - ChildrenMessageElement: &ChildrenMessageElement{ - Children: []MessageElement{ - &MessageElementText{ - Content: "testtest2", - }, - }, - }, - }, - }, - }, - { - Raw: `test