builder.go 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package web
  2. import (
  3. "bytes"
  4. "context"
  5. "net/http"
  6. "time"
  7. "github.com/NYTimes/gziphandler"
  8. h "github.com/theplant/htmlgo"
  9. )
  10. type Builder struct {
  11. EventsHub
  12. layoutFunc LayoutFunc
  13. }
  14. func New() (b *Builder) {
  15. b = new(Builder)
  16. b.layoutFunc = defaultLayoutFunc
  17. return
  18. }
  19. func (b *Builder) LayoutFunc(mf LayoutFunc) (r *Builder) {
  20. if mf == nil {
  21. panic("layout func is nil")
  22. }
  23. b.layoutFunc = mf
  24. return b
  25. }
  26. func (p *Builder) EventFuncs(vs ...interface{}) (r *Builder) {
  27. p.addMultipleEventFuncs(vs...)
  28. return p
  29. }
  30. type ComponentsPack string
  31. var startTime = time.Now()
  32. func PacksHandler(contentType string, packs ...ComponentsPack) http.Handler {
  33. return Default.PacksHandler(contentType, packs...)
  34. }
  35. func (b *Builder) PacksHandler(contentType string, packs ...ComponentsPack) http.Handler {
  36. var buf = bytes.NewBuffer(nil)
  37. for _, pk := range packs {
  38. // buf = append(buf, []byte(fmt.Sprintf("\n// pack %d\n", i+1))...)
  39. // buf = append(buf, []byte(fmt.Sprintf("\nconsole.log('pack %d, length %d');\n", i+1, len(pk)))...)
  40. buf.WriteString(string(pk))
  41. buf.WriteString("\n\n")
  42. }
  43. body := bytes.NewReader(buf.Bytes())
  44. return gziphandler.GzipHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  45. w.Header().Set("Content-Type", contentType)
  46. http.ServeContent(w, r, "", startTime, body)
  47. }))
  48. }
  49. func NoopLayoutFunc(r *http.Request, injector *PageInjector, body string) (output string, err error) {
  50. output = body
  51. return
  52. }
  53. func defaultLayoutFunc(r *http.Request, injector *PageInjector, body string) (output string, err error) {
  54. root := h.HTML(
  55. h.Head(
  56. injector.GetHeadHTMLComponent(),
  57. ),
  58. h.Body(
  59. h.Div(
  60. h.RawHTML(body),
  61. ).Id("app").Attr("v-cloak", true),
  62. injector.GetTailHTMLComponent(),
  63. ).Class("front"),
  64. )
  65. buf := bytes.NewBuffer(nil)
  66. ctx := new(EventContext)
  67. ctx.R = r
  68. err = h.Fprint(buf, root, WrapEventContext(context.TODO(), ctx))
  69. if err != nil {
  70. return
  71. }
  72. output = buf.String()
  73. return
  74. }