From 8939bc5b2441ed9a75e83403bb31cb84a0fdce9c Mon Sep 17 00:00:00 2001 From: WindowsSov8forUs Date: Fri, 12 Apr 2024 15:45:46 +0800 Subject: [PATCH] =?UTF-8?q?update:=20=E9=80=82=E9=85=8D=E4=BB=BB=E6=84=8F?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=85=83=E7=B4=A0=E7=9A=84=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E7=8A=B6=E5=86=B5=EF=BC=8C=E9=99=A4=E7=BA=AF=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E4=BB=A5=E5=A4=96=E6=89=80=E6=9C=89=E5=85=83=E7=B4=A0=E9=83=BD?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=8B=A5=E6=9C=89=E4=BB=BB=E6=84=8F=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E4=BB=A5=E5=8F=8A=E5=AD=90=E5=85=83=E7=B4=A0=E4=B8=94?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E8=8E=B7=E5=8F=96=EF=BC=8C=E5=90=8C=E6=97=B6?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=BA=86=E8=BE=93=E5=87=BA=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/message/message_element.go | 57 ++- pkg/message/message_element_basic.go | 78 ++- pkg/message/message_element_decorative.go | 200 +++++--- pkg/message/message_element_meta.go | 44 +- pkg/message/message_element_oprator.go | 26 +- pkg/message/message_element_resource.go | 197 ++++++- pkg/message/message_element_typography.go | 51 +- pkg/message/parser.go | 2 - pkg/message/parser_test.go | 16 +- pkg/message/parser_test_data.go | 595 ++-------------------- pkg/message/xhtml.go | 2 +- 11 files changed, 550 insertions(+), 718 deletions(-) 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() + "" + 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` + return `<` + e.Tag() + result + `>` + childrenStr + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + `` } 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 + "" } 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 + `` + return "<" + e.Tag() + result + ">" + childrenStr + "" } 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

- -
`, - TargetRaw: `

test

`, - Elements: []MessageElement{ - &MessageElementMessage{ - ChildrenMessageElement: &ChildrenMessageElement{ - Children: []MessageElement{ - &MessageElementAt{ - Id: "1", - Name: "test", - }, - &MessageElementAt{ - Id: "2", - Name: "test2", - }, - &MessageElmentBr{}, - &MessageElmentP{ - ChildrenMessageElement: &ChildrenMessageElement{ - Children: []MessageElement{ - &MessageElementText{ - Content: "test", - }, - }, - }, - }, - &MessageElementImg{ - Src: "https://example.com", - }, - &MessageElementAudio{ - Src: "https://example.com", - }, - &MessageElmentP{ - ChildrenMessageElement: &ChildrenMessageElement{ - /** - bold - sup - sub - spoiler - code - 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 - -`, - TargetRaw: "yarn add nitori\n yarn run test\n npm publish", - Elements: []MessageElement{ - &MessageElementMessage{ - ChildrenMessageElement: &ChildrenMessageElement{ - Children: []MessageElement{ - &MessageElementCode{ - ChildrenMessageElement: &ChildrenMessageElement{ - Children: []MessageElement{ - &MessageElementText{ - Content: "yarn add nitori\n yarn run test\n npm publish", - }, - }, - }, - }, - }, - }, - }, - }, - }, + `I can eat glass and it doesn't hurt me.`, + ``, + ``, + ``, + } +} + +func _getResourceRawMessage() []string { + return []string{ + ``, + `