element.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package element
  2. import (
  3. "git.nspix.com/golang/pgenr/internal/pool"
  4. "golang.org/x/net/html/atom"
  5. "html"
  6. "strconv"
  7. "strings"
  8. )
  9. type (
  10. Option func(t *element)
  11. Element interface {
  12. Html() string
  13. }
  14. Attrs map[string]string
  15. element struct {
  16. Name atom.Atom
  17. Attr Attrs
  18. Content string
  19. }
  20. )
  21. func renderTag(tag string, attrs Attrs, content string) string {
  22. br := pool.Get()
  23. defer pool.Put(br)
  24. br.WriteString("<" + tag)
  25. if len(attrs) > 0 {
  26. for k, v := range attrs {
  27. if !strings.HasPrefix(k, "data-") {
  28. if atom.Lookup([]byte(k)) == 0 {
  29. continue
  30. }
  31. }
  32. br.WriteString(" " + k + "=" + strconv.Quote(v))
  33. }
  34. }
  35. br.WriteString(">")
  36. br.WriteString(content)
  37. br.WriteString("</" + tag + ">")
  38. return br.String()
  39. }
  40. func beginTag(tag string, attrs Attrs) string {
  41. br := pool.Get()
  42. defer pool.Put(br)
  43. br.WriteString("<" + tag)
  44. if len(attrs) > 0 {
  45. for k, v := range attrs {
  46. if atom.Lookup([]byte(k)) == 0 {
  47. continue
  48. }
  49. br.WriteString(" " + k + "=\"" + v + "\" ")
  50. }
  51. }
  52. br.WriteString(">")
  53. return br.String()
  54. }
  55. func endTag(tag string) string {
  56. br := pool.Get()
  57. defer pool.Put(br)
  58. br.WriteString("</" + tag + ">")
  59. return br.String()
  60. }
  61. func WithAttribute(label string, value string) Option {
  62. return func(t *element) {
  63. if t.Attr == nil {
  64. t.Attr = make(map[string]string)
  65. }
  66. t.Attr[label] = value
  67. }
  68. }
  69. func (element *element) Html() string {
  70. return element.String()
  71. }
  72. func (element *element) String() string {
  73. return renderTag(element.Name.String(), element.Attr, html.EscapeString(element.Content))
  74. }
  75. func NewElement(atom atom.Atom, content string, opts ...Option) *element {
  76. e := &element{Name: atom, Content: content}
  77. for _, cb := range opts {
  78. cb(e)
  79. }
  80. return e
  81. }