package htmlx import ( "github.com/d5/tengo/v2" "strings" "html" "fmt" ) const RawTag = "raw" // The type implements basic // way to structrize HTML elements. type Element struct { tengo.ObjectImpl Tag string Attr map[string] string Children []*Element // The value makes sense only if // the tag is the "raw" Content string } func (el *Element) TypeName() string { return "*HTMLElement" } // The method renders the element to it's // HTML representation. func (el *Element) String() string { if el.Tag == RawTag { return html.EscapeString(el.Content) } var b strings.Builder fmt.Fprintf(&b, "<%s", el.Tag) for k, v := range el.Attr { fmt.Fprintf(&b, " %s=%q", k, v) } fmt.Fprint(&b, ">") for _, child := range el.Children { if child == nil { continue } fmt.Fprint(&b, child.String()) } fmt.Fprintf(&b, "", el.Tag) return b.String() } func (el *Element) Body(els ...*Element) *Element { el.Children = els return el } func (el *Element) IndexGet( index tengo.Object, ) (tengo.Object, error) { arg, ok := tengo.ToString(index) if !ok { return nil, tengo.ErrInvalidIndexValueType } switch arg { case "body" : return &tengo.UserFunction{ Name: "Element.Body", Value: func( args ...tengo.Object, ) (tengo.Object, error) { s := []*Element{} for _, arg := range args { el, ok := arg.(*Element) if !ok { str, ok := tengo.ToString(arg) if ok { s = append(s, &Element{ Tag: RawTag, Content: str, }) } continue } s = append(s, el) } return el.Body(s...), nil }, }, nil } return nil, nil }